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).