sql >> Base de Datos >  >> NoSQL >> MongoDB

Cómo usar una declaración SQL LIKE en MongoDB

Para este tutorial, usaremos el official dummy dataset , que contiene numerosos documentos de restaurantes de todo el área de Nueva York.

Aquí hay un ejemplo de la estructura básica del documento en esta colección, usando .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"
}

El poder de encontrar

La pieza más importante del rompecabezas al buscar dentro de una colección de MongoDB es el simple pero flexible db.collection.find() método.

Con .find() , puede consultar fácilmente una colección de documentos, pasando algunos parámetros simples y devolver un cursor . Un cursor es simplemente un conjunto de resultados y se puede iterar para manipular o hacer uso de los documentos a los que apunta el cursor .

Como un ejemplo simple de .find() en acción, intentaremos encontrar todos los restaurantes de nuestra colección que sirvan Hamburgers como su 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" }
...

El conjunto de resultados es bastante grande, por lo que una mejor medida para nuestros ejemplos de prueba sería encadenar .count() método en .find() para ver simplemente cuántos documentos coincidieron con nuestra consulta:

> db.restaurants.find( { cuisine: "Hamburgers" } ).count()
433

¡Son muchas hamburguesas!

Buscar similitudes de palabras usando Regex

Ahora que estamos usando .find() para consultar nuestra colección, podemos modificar nuestra sintaxis ligeramente y comenzar a buscar coincidencias basadas en una palabra o frase que puede ser un parcial coincidencia dentro de un campo dado, similar a LIKE operador para motores SQL.

El truco es utilizar regular expressions (o regex para abreviar), que es básicamente una cadena de texto que define un patrón de búsqueda. Hay una serie de regex motores que están escritos en una sintaxis ligeramente diferente, pero los fundamentos son básicamente los mismos, y en este caso, MongoDB usa el Perl Regex (PCRE) motor.

En el nivel más básico, una regex expresión es una cadena (serie de caracteres) encerrada en ambos lados por una sola barra (/ ).

Por ejemplo, si queremos usar regex para realizar la misma consulta anterior y averiguar cuántos restaurantes sirven Hamburgers , podemos reemplazar nuestra cadena "Hamburgers" con /Hamburgers/ en cambio:

> db.restaurants.find( { cuisine: /Hamburgers/ } ).count()
433

Los observadores entusiastas pueden reconocer que efectivamente no hemos cambiado nada sobre la consulta real que estamos realizando; simplemente estamos buscando todos los documentos donde la cuisine el campo es igual a la cadena "Hamburgers" .

Dicho esto, simplemente usando regex en lugar de una "cadena entrecomillada" normal, podemos comenzar a buscar coincidencias parciales de palabra/frase en su lugar.

Por ejemplo, echemos un vistazo al borough campo para tener una mejor idea de cómo funciona esto. Primero notaremos que hay seis condados en total dentro de nuestra colección:

> db.restaurants.distinct('borough')
[
        "Brooklyn",
        "Bronx",
        "Manhattan",
        "Queens",
        "Staten Island",
        "Missing"
]

Ahora usemos regex para averiguar cuántos restaurantes hay en el Bronx municipio:

> db.restaurants.find( { borough: /Bronx/ } ).count()
2338

Pero imagina que queremos encontrar el número de restaurantes donde borough empieza con los tres primeros caracteres "Bro" . Modificaríamos nuestra regex muy levemente, así:

> db.restaurants.find( { borough: /^Bro/ } ).count()
8424

Estamos viendo más de 6000 documentos adicionales en este conjunto de resultados, lo que tiene sentido porque no solo estamos obteniendo resultados donde el borough es "Bronx" , pero también todo para "Brooklyn" también.

El carácter de intercalación (^ ) especifica la ubicación en nuestra cadena que debería ser el comienzo , por lo que si tuviéramos un documento en el que esas tres letras estuvieran en medio del campo, no obtendríamos una coincidencia.

Como otro ejemplo rápido, busquemos en cualquier lugar en el campo para los caracteres "at" , que debería darnos resultados tanto para "Manhattan" y "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

Efectivamente, nuestra consulta final ha combinado los dos conjuntos de resultados en uno.

Puede notar que aunque nuestros personajes "AT" están en mayúsculas en nuestro regex cadena, pero son minúsculas en los registros de documentos reales, todavía devolvimos resultados. Esto se debe a que también agregamos el i especial indicador que sigue a nuestra barra inclinada de cierre de expresiones regulares (/ ). Esto informa a la regex motor en el que queremos que la búsqueda sea case insensitive , coincidiendo independientemente de mayúsculas o minúsculas.