2011-01-19 14 views
13

tengo un requisito en las que necesito para ejecutar una consulta MongoDB como la siguiente:pregunta en relación con el encadenamiento de múltiples criterios any_of #Mongoid

db.collection.find({ $or : [{"field1" : "value1"}, {"field2" : "value2"}], 
$or : [{"field3" : "value3"}, {"field4" : "value4"}]}) 

es decir

 
(field1 == value 1 or field2 == value2) and (field3 == value3 or field4 
== value4) 

que quiero lograr esto a través de criterios de encadenamiento porque la consulta se forma dinámicamente desde diferentes partes del código. Pero si intento hacer algo como lo siguiente

 
criteria = Collection.any_of({"field1" => "value1"}, {"field2" => 
"value2"}) 
criteria = criteria.any_of({"field3" => "value3"}, {"field4" => "value4"}) 

consigo la consulta resultante, donde todos estos se combinan en una sola $ o declaración como

 
db.collection.find({ $or : [{"field1" : "value1"}, {"field2" : "value2"}, 
{"field3" : "value3"}, {"field4" : "value4"}]}) 

¿Cuál es la forma de conseguir "y" de los dos "any_of" utilizando el encadenamiento de criterios?

+0

qué versión de Mongoid usas? – shingara

+0

Yo uso 2.0.0.beta.20 – Rakeesh

+0

Hay un problema con la forma any_of/$ o es manejado por Mongoid. Ha abierto un problema en Github: https://github.com/mongoid/mongoid/issues/issue/569 – Rakeesh

Respuesta

4

Puedes hacerlo con evitar any_of.

criteria = Collection.where('$or' => [{"field1" => "value1"}, {"field2" => "value2"}]) 
criteria = criteria.where('$or' => [{"field3" => "value3"}, {"field4" => "value4"}]) 
+3

Intenté esto. Pero también produjo el mismo resultado donde todos los campos de consulta se combinaron en una sola consulta "$ o", similar a usar any_of. – Rakeesh

+0

y puede hacerlo con éxito en la consola MongoDB? – shingara

+0

Sí: funciona desde la consola. – Rakeesh

4

puede escribir esto con MongoId 2.4.0:

Collection.all_of({"$or" => [{"field1" => "value1"}, {"field2" => "value2"}]}, {"$or" => [{"field3" => "value3"}, {"field4" => "value4"}]}) 
+0

Esto probablemente incluirá demasiados documentos. En mi caso, quiero documentos que satisfagan AMBOS $ o condiciones. – Dmitry

+1

Collection.all_of agrega un criterio que especifica las expresiones que deben coincidir para devolver los resultados. La operación MongoDB correspondiente es $ y. http://two.mongoid.org/docs/querying/criteria.html#all_of. Entonces esto debería ser algo así como ((campo1 == valor1) O (campo2 == valor2)) AND ((campo3 == valor3) O (campo4 == valor4)). – TlmaK0

1

Me tomó por siempre para conseguir este derecho, pero esto es lo que funcionó para mí:

scope :for_user, lambda {|user| 
    any_of(
     {recipient_id: Moped::BSON::ObjectId.from_string(user.id)}, 
     {sender_id: Moped::BSON::ObjectId.from_string(user.id)}, 
     {sender_email: user.email}, 
     {recipient_email: user.email} 
    ) 
    } 

Tienes para asegurarse de ajustar los criterios individuales para su condición $or en {} para que anide correctamente el OR. (Usando Mongoid3/Moped)

+0

gracias, eso funcionó para mí y mantiene los términos de búsqueda claros – dax

0

Este sigue siendo el caso. Pude solucionar esto solo al utilizar Ruby Mongo Driver API directamente.

2

Para Mongoid 3 y 4 hay una manera relativamente agradable de encadenamiento o criterios sin fusionarse.

TL; DR

MyModel.all_of(MyModel.xxx.selector, MyModel.yyy.selector) 

Mongoid mantenedor Durran mostró el truco anteriormente en este tema Github: https://github.com/mongoid/mongoid/issues/2170

Puede arbitrariamente criterios de cadena usando la misma técnica y algunos array engaño como este:

selectors = [] 
selectors << MyModel.search(term) if term 
selectors << MyModel.some_any_of if some_condition 
selectors << MyModel.some_other_any_of if some_other_condition 
... 
MyMode..all_of(*selectors) 

Cada fila agregará y c ondición.

También vale la pena señalar que no es necesario crear cada selector del modelo. Puede obtener un alcance inicial de su sistema de permisos o algo así como simplemente llamar a .selector antes de agregar más criterios.

Cuestiones relacionadas