MongoDB
 sql >> Base de Dados >  >> NoSQL >> MongoDB

Como usar uma instrução SQL LIKE no MongoDB


Para este tutorial, usaremos o official dummy dataset , que contém vários documentos de restaurantes de toda a área de Nova York.

Aqui está um exemplo da estrutura básica do documento nesta coleção, usando o .findOne() método:
> db.restaurants.findOne()
{
        "_id" : ObjectId("56c651e7d84ccfde319961af"),
        "address" : {
                "building" : "469",
                "coord" : [
                        -73.961704,
                        40.662942
                ],
                "street" : "Flatbush Avenue",
                "zipcode" : "11225"
        },
        "borough" : "Brooklyn",
        "cuisine" : "Hamburgers",
        "grades" : [
                {
                        "date" : ISODate("2014-12-30T00:00:00Z"),
                        "grade" : "A",
                        "score" : 8
                },
                {
                        "date" : ISODate("2014-07-01T00:00:00Z"),
                        "grade" : "B",
                        "score" : 23
                },
                {
                        "date" : ISODate("2013-04-30T00:00:00Z"),
                        "grade" : "A",
                        "score" : 12
                },
                {
                        "date" : ISODate("2012-05-08T00:00:00Z"),
                        "grade" : "A",
                        "score" : 12
                }
        ],
        "name" : "Wendy'S",
        "restaurant_id" : "30112340"
}

O poder da descoberta


A peça mais importante do quebra-cabeça ao pesquisar em uma coleção do MongoDB é o simples e flexível db.collection.find() método.

Com .find() , você pode consultar facilmente uma coleção de documentos, passando alguns parâmetros simples e retornar um cursor . Um cursor é simplesmente um conjunto de resultados e pode ser iterado para manipular ou usar os documentos apontados pelo cursor .

Como um exemplo simples do .find() em ação, tentaremos encontrar todos os restaurantes em nossa coleção que servidor Hamburgers como sua cuisine :
>db.restaurants.find( { cuisine: "Hamburgers" } )
{ "_id" : ObjectId("56c651e7d84ccfde319961af"), "address" : { "building" : "469", "coord" : [ -73.961704, 40.662942 ], "street" : "Flatbush Avenue", "zipcode" : "11225" }, "borough" : "Brooklyn", "cuisine" : "Hamburgers", "grades" : [ { "date" : ISODate("2014-12-30T00:00:00Z"), "grade" : "A", "score" : 8 }, { "date" : ISODate("2014-07-01T00:00:00Z"), "grade" : "B", "score" : 23 }, { "date" : ISODate("2013-04-30T00:00:00Z"), "grade" : "A", "score" : 12 }, { "date" : ISODate("2012-05-08T00:00:00Z"), "grade" : "A", "score" : 12 } ], "name" : "Wendy'S", "restaurant_id" : "30112340" }
...

O conjunto de resultados é bastante grande, portanto, uma medida melhor para nossos exemplos de teste seria encadear o .count() método para .find() para simplesmente ver quantos documentos corresponderam à nossa consulta:
> db.restaurants.find( { cuisine: "Hamburgers" } ).count()
433

São muitos hambúrgueres!

Pesquisando semelhanças de palavras usando Regex


Agora que estamos usando .find() para consultar nossa coleção, podemos modificar levemente nossa sintaxe e começar a procurar correspondências com base em uma palavra ou frase que pode ser parcial corresponder dentro de um determinado campo, semelhante ao LIKE operador para motores SQL.

O truque é utilizar regular expressions (ou regex para abreviar), que é basicamente uma string de texto que define um padrão de pesquisa. Existem várias regex motores que são escritos em sintaxe ligeiramente diferente, mas os fundamentos são basicamente os mesmos e, neste caso, o MongoDB usa o Perl Regex (PCRE) motor.

No nível mais básico, um regex expressão é uma string (série de caracteres) delimitada em ambos os lados por uma única barra (/ ).

Por exemplo, se quisermos usar regex para realizar a mesma consulta acima e descobrir quantos restaurantes servem Hamburgers , podemos substituir nossa string "Hamburgers" com /Hamburgers/ em vez de:
> db.restaurants.find( { cuisine: /Hamburgers/ } ).count()
433

Observadores atentos podem reconhecer que não alteramos nada na consulta real que estamos realizando - ainda estamos simplesmente procurando todos os documentos em que a cuisine campo é igual a a string "Hamburgers" .

Dito isso, simplesmente usando regex em vez de uma “string entre aspas” normal, podemos começar a procurar correspondências parciais de palavra/frase em vez de.

Por exemplo, vejamos o borough campo para ter uma ideia melhor de como isso funciona. Primeiro, vamos notar que existem seis distritos no total em nossa coleção:
> db.restaurants.distinct('borough')
[
        "Brooklyn",
        "Bronx",
        "Manhattan",
        "Queens",
        "Staten Island",
        "Missing"
]

Agora vamos usar regex para descobrir quantos restaurantes estão no Bronx bairro:
> db.restaurants.find( { borough: /Bronx/ } ).count()
2338

Mas imagine que queremos encontrar o número de restaurantes onde borough começa com os três primeiros caracteres "Bro" . Modificaríamos nossa regex muito ligeiramente, assim:
> db.restaurants.find( { borough: /^Bro/ } ).count()
8424

Estamos vendo mais de 6.000 documentos adicionais neste conjunto de resultados, o que faz sentido porque não apenas estamos obtendo resultados onde o borough é "Bronx" , mas também tudo para "Brooklyn" também.

O caractere acento circunflexo (^ ) especifica o local em nossa string que deve ser o início , então, se tivéssemos um documento em que essas três letras estivessem no meio do campo, não obteríamos uma correspondência.

Como outro exemplo rápido, vamos pesquisar em qualquer lugar no campo para os caracteres "at" , que deve nos dar resultados tanto para "Manhattan" e "Staten Island" :
> db.restaurants.find( { borough: /Manhattan/ } ).count()
10259

> db.restaurants.find( { borough: /Staten Island/ } ).count()
969

> db.restaurants.find( { borough: /AT/i } ).count()
11228

Com certeza, nossa consulta final combinou os dois conjuntos de resultados em um.

Você pode notar que, embora nossos caracteres "AT" são maiúsculas em nossa regex string, mas são minúsculas nos registros de documentos reais, ainda retornamos resultados. Isso ocorre porque também adicionamos o i especial sinalizador seguindo nossa barra de fechamento regex (/ ). Isso informa a regex motor que queremos que a pesquisa seja case insensitive , correspondendo independentemente de maiúsculas ou minúsculas.