2011-11-23 21 views
16

Usando Pymongo para este escenario.Mongodb - ¿Cómo encontrar cadenas en múltiples campos?

Tengo el usuario que tiene el correo electrónico, first_name, last_name.

estoy usando este Pymongo fragmento:

user_found = users.find({'$or':[ 
      {'email':{'$regex':searchString, '$options':'i'}}, 
      {'first_name':{'$regex':searchString, '$options':'i'}}, 
      {'last_name':{'$regex':searchString, '$options':'i'}}]}) 

este ejemplo funciona, si quiero encontrar searchString que en:

  • correo electrónico, o
  • nombre apellido, o
  • apellidos

ahora necesito también encuentre searchString en first_name + last_name combinado.

¿cómo puedo hacer eso? ¿Hay alguna manera en mongo, a través de la consulta, de combinar los dos en un "nombre completo" y luego buscar el nombre completo?

Respuesta

13

La manera más fácil es agregar un campo de matriz y rellenarlo con todas las variantes que desee buscar. Indexe ese campo de matriz.

De esta manera solo necesita un índice y su búsqueda en todos los campos es simple y no cambia cuando desea buscar en alguna nueva variante de búsqueda. También puede normalizar el texto que usted pone en la matriz de búsqueda, por ejemplo, la caja inferior, eliminando puntuacion etc.

Ver https://stackoverflow.com/q/8206188/224370

Editar: Documentación de MongoDB cubre ahora keyword search y la nueva característica full-text search.

+1

Excelente respuesta sucinta. Qué pro. –

+0

@lan Mercer Mi búsqueda funciona bien para múltiples campos, solo necesito realizar buscar en campos combinados [fname + sname], ¿Necesito crear un índice para ambos campos para hacerlo? Por favor, abreviados, ¿algún ejemplo? –

+0

@AqibMumtaz publique una nueva pregunta con ejemplos de lo que está tratando de hacer: los comentarios no son el mejor lugar para hacer nuevas preguntas. –

0

Tuve el mismo problema. Ya usé la búsqueda de cadenas regex, así que mi solución fue:

generar una colección de ayuda. Aquí combino toda la cadena correspondiente, como:

{ 
    search_field: email + " " + first_name + " " + last_name, 
    ref_id: (id to real object) 
} 

Luego utilizo una expresión regular para conformar lo que permite que ésta sea buscado:

// logic found here: http://stackoverflow.com/questions/10870372/regex-match-if-string-contain-all-the-words-or-a-condition 
var words = query.split(/[ ,]+/); 
var regstr = ""; 
for (var i = 0; i < words.length; ++i) { 
    var word = words[i]; 
    regstr += "(?=.*?\\b" + word + ")"; 
} 
regstr += "^.*$"; 
regex = new RegExp(regstr, "i"); 

Esto entonces también da cierta flexibilidad sobre el orden.

La búsqueda no es la más rápida, ya que todavía utiliza expresiones regulares en todos los elementos, pero está bien para mí. (También índice de la colección en search_field

la obtención de resultados también se convierte en una llamada anidada, ya que primero es necesario obtener los _ids que realmente desea, y luego se puede consultar por ellos, así:.

connection.find({ "search_field" : regex }, { _id: 0, ref_id: 1 }, { limit: limit, skip: start }).toArray(function (err, docs) { 
    if (err) throw err; 
    // map array of documents into simple array of ids 
    var ids = []; 
    for (var i = 0; i < docs.length; ++i) 
    { 
     var doc = docs[i]; 
     ids.push(doc.ref_id); 
    } 
    if (ids.length > 0) 
     MongooseEmails.find({ "_id": { $in: ids } }, function (err, docres) { 
      if (err) throw err; 
      res.send(JSON.stringify(docsres)); 
     }); 
    else 
     res.send(""); 
}); 

Este es un código editado .. tal vez hay un error de sintaxis, en general, me funciona.

Cuestiones relacionadas