mongodb - similar - regex robomongo
comodín de prefijo mongoDB: búsqueda de texto completo($ text) encuentra parte con cadena de búsqueda (6)
Como dijo francadaval, el índice de texto está buscando por términos, pero si combina expresiones regex
y text-index
, debería ser bueno.
mycoll.find({ $or: [
{
$text: { $search: "super"}
}, {"Columname":{
$regex: ''uper'',
$options: ''i''
}
] })
Además, asegúrese de tener un índice normal aplicado a la columna que no sea el índice de texto
Tengo mongodb con un $text-Index
y elementos como este:
{
foo: "my super cool item"
}
{
foo: "your not so cool item"
}
Si busco con
mycoll.find({ $text: { $search: "super"} })
obtengo el primer artículo (correcto).
Pero también quiero buscar con "uper" para obtener el primer elemento, pero si intento:
mycoll.find({ $text: { $search: "uper"} })
No obtengo ningún resultado
Mi pregunta: si hay una forma de usar $ text, ¿encuentra resultados con una parte de la cadena de búsqueda? (por ejemplo, como ''%uper%''
en mysql
)
Atención: no solicito una búsqueda exclusiva de expresiones regulares. ¡Solicito una búsqueda de expresiones regulares dentro de $ text-search!
Debería funcionar con /uper/
.
Ver http://docs.mongodb.org/manual/reference/operator/query/regex/ para más detalles.
Editar:
Según solicitud en los comentarios:
La solución no estaba destinada a dar realmente lo que el PO solicitó , sino lo que necesitaba para resolver el problema.
Como las búsquedas $regex
no funcionan con índices de texto, una búsqueda simple de expresiones regulares sobre un campo indexado debería dar el resultado esperado, aunque no utilizando los medios solicitados.
En realidad, es bastante fácil hacer esto:
db.collection.insert( {foo: "my super cool item"} )
db.collection.insert( {foo: "your not so cool item"})
db.collection.ensureIndex({ foo: 1 })
db.collection.find({''foo'': /uper/})
nos da el resultado esperado:
{ "_id" : ObjectId("557f3ba4c1664dadf9fcfe47"), "foo" : "my super cool item" }
Una explicación adicional nos muestra que el índice se utilizó de manera eficiente:
{
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "test.collection",
"indexFilterSet" : false,
"parsedQuery" : {
"foo" : /uper/
},
"winningPlan" : {
"stage" : "FETCH",
"inputStage" : {
"stage" : "IXSCAN",
"filter" : {
"foo" : /uper/
},
"keyPattern" : {
"foo" : 1
},
"indexName" : "foo_1",
"isMultiKey" : false,
"direction" : "forward",
"indexBounds" : {
"foo" : [
"[/"/", {})",
"[/uper/, /uper/]"
]
}
}
},
"rejectedPlans" : [ ]
},
"serverInfo" : {
// skipped
},
"ok" : 1
}
Para resumir: No, no puede reutilizar un índice de $text
, pero puede hacer la consulta de manera eficiente. Al igual que en la característica Implementar autocompletar utilizando la búsqueda de MongoDB , probablemente uno podría ser aún más eficiente utilizando un enfoque de mapa / reducción, eliminando la redundancia y las palabras de parada innecesarias de los índices, a costa de no ser en tiempo real.
Lo que está tratando de hacer en su segundo ejemplo es prefijo de búsqueda comodín en su colección mycoll
en el campo foo
. Esto no es algo para lo que está diseñada la función de búsqueda de texto y no es posible hacerlo con $text
operator. Este comportamiento no incluye búsqueda de prefijo de comodín en ningún token determinado en el campo indexado. Sin embargo, alternativamente puede realizar la búsqueda de expresiones regulares como otros sugirieron. Aquí está mi tutorial:
>db.mycoll.find()
{ "_id" : ObjectId("53add9364dfbffa0471c6e8e"), "foo" : "my super cool item" }
{ "_id" : ObjectId("53add9674dfbffa0471c6e8f"), "foo" : "your not so cool item" }
> db.mycoll.find({ $text: { $search: "super"} })
{ "_id" : ObjectId("53add9364dfbffa0471c6e8e"), "foo" : "my super cool item" }
> db.mycoll.count({ $text: { $search: "uper"} })
0
El operador de $text
admite la búsqueda de una sola palabra, buscar una o más palabras o buscar una frase. El tipo de búsqueda que desea no es compatible
La solución de expresiones regulares:
> db.mycoll.find({foo:/uper/})
{ "_id" : ObjectId("53add9364dfbffa0471c6e8e"), "foo" : "my super cool item" }
>
La respuesta a su pregunta final: para hacer mysql style %super%
en mongoDB lo más probable es que tenga que hacer:
db.mycoll.find( { foo : /.*super.*/ } );
No es posible hacerlo con $text
operator.
Los índices de texto se crean con los términos incluidos en el valor de cadena o en una matriz de cadenas y la búsqueda se basa en esos idexes.
Solo puedes agrupar términos en un paquete pero no formar parte de ellos.
Lea la referencia del operador de $text
y la descripción de los índices de texto .
No tengo suficiente reputación para comentar la solución de jasenkoh, pero esta es claramente la mejor manera de lidiar con esta situación.
En situación OP, yo:
db.mycoll.createIndex( { foo: "text" } )
db.mycoll.createIndex( { foo: 1 } )
db.mycoll.find({$or: [{$text: {$search: ''uper''}}, {foo: {$regex: ''uper''}}]})
Para un mejor rendimiento (pero resultados ligeramente diferentes), reemplace la última línea con:
db.mycoll.find({$or: [{$text: {$search: ''uper''}}, {foo: {$regex: ''^uper''}}]})
Podrías haber logrado es como-
db.mycoll.find( {foo: { $regex : /uper/i } })
Aquí ''yo'' es una opción, denota búsqueda insensible a mayúsculas y minúsculas