Búsqueda de MongoDB para cada dictado en la lista en la colección

Tengo una collection contiene una list de dicts y quiero buscar si algún dictado contiene dos key:values específicas key:values .

Entonces, por ejemplo, quiero encontrar una en la que un dict contenga un nombre y un apellido específicos. Esta es mi colección:

 { "names": [ { "firstName": "bob", "lastName": "jones", "age": "34", "gender": "m" }, { "firstName": "alice", "lastName": "smith", "age": "56", "gender": "f" }, { "firstName": "bob", "lastName": "smith", "age": "19", "gender": "m" }, ] } 

Quiero ver si hay un registro con Bob Smith como nombre y apellido, estoy buscando esto como:

 first = 'bob' last = 'smith' nameExists = db.user.find_one({'$and':[{'names.firstName':first,'names.lastName':last}]}) 

¿Recuperaría esta consulta el único registro para Bob Smith?

Si bien se menciona que, de hecho, el $and operador no son necesarios, en cualquiera de los dos formularios no es la consulta que desea. Considera lo siguiente:

 db.user.find_one({ 'names.firstName': 'alice','names.lastName': 'jones' }) 

De hecho, esto coincide con el registro dado, ya que ambos elementos tienen los valores de “primer nombre” igual a “alice” y “apellido” igual a “jones”. Pero, por supuesto, el problema aquí es simple, ya que no hay ningún elemento real en la matriz que tenga un sub-documento para ambos valores.

Para hacer coincidir donde un elemento de matriz contiene “ambos” los criterios dados, debe usar el operador $elemMatch . Esto aplica la condición de consulta a los “elementos” de la matriz.

 db.user.find_one({ 'names': { '$elemMatch': { 'firstName': 'alice','lastName': 'smith' } }) 

Y, por supuesto, si probó “alice” y “jones”, no coincidirá, ya que ningún elemento contiene esa operación.

¡Casi!

  nameExists = db.user.find_one({'$and':[{'names.firstName':first},{'names.lastName':last}]}) 

Debe separar las preguntas en paréntesis {} separados.

Ni siquiera necesitas agregar el $ y el parámetro. En mongoDB, los campos separados por comas dentro de una consulta están unidos por un operador AND implícito , por lo que usar simplemente {‘names.firstName’: primero, ‘names.lastName’: last} dentro de find_one funcionará.

De todos modos, eso es solo una corrección de “código limpio”; Su código funcionará correctamente mientras realiza una operación “y” con un solo elemento (tenga en cuenta que la lista utilizada para el parámetro $ y contiene un solo diccionario).