strings - Condición de consulta MongoDb al comparar 2 campos
mongodb gte date (4)
En caso de que el rendimiento sea más importante que la legibilidad y siempre que su condición consista en operaciones aritméticas simples, puede usar la canalización de agregación. Primero, use $ project para calcular el lado izquierdo de la condición (tome todos los campos al lado izquierdo). Luego use $ match para comparar con una constante y filtro. De esta forma evitará la ejecución de javascript. A continuación está mi prueba en python:
import pymongo
from random import randrange
docs = [{''Grade1'': randrange(10), ''Grade2'': randrange(10)} for __ in range(100000)]
coll = pymongo.MongoClient().test_db.grades
coll.insert_many(docs)
Usando agregado:
%timeit -n1 -r1 list(coll.aggregate([
{
''$project'': {
''diff'': {''$subtract'': [''$Grade1'', ''$Grade2'']},
''Grade1'': 1,
''Grade2'': 1
}
},
{
''$match'': {''diff'': {''$gt'': 0}}
}
]))
1 loop, lo mejor de 1: 192 ms por ciclo
Usando find y $ donde:
%timeit -n1 -r1 list(coll.find({''$where'': ''this.Grade1 > this.Grade2''}))
1 loop, lo mejor de 1: 4.54 s por loop
Tengo una colección T
, con 2 campos: Grade1
y Grade2
, y quiero seleccionar aquellos con condición Grade1 > Grade2
, ¿cómo puedo obtener una consulta como en MySQL?
Select * from T Where Grade1 > Grade2
Puede usar $expr (operador de versión de 3.6 mongo) para usar las funciones de agregación en la consulta normal.
Comparar query operators
versus aggregation comparison operators
.
Consulta regular:
db.T.find({$expr:{$gt:["$Grade1", "$Grade2"]}})
Consulta de Agregación:
db.T.aggregate({$match:{$expr:{$gt:["$Grade1", "$Grade2"]}}})
Puede usar un $ donde. Solo tenga en cuenta que será bastante lento (tiene que ejecutar el código Javascript en cada registro) así que combine con las consultas indexadas si puede.
db.T.find( { $where: function() { return this.Grade1 > this.Grade2 } } );
o más compacto:
db.T.find( { $where : "this.Grade1 > this.Grade2" } );
UPD para mongodb v.3.6 +
puede usar $expr
como se describe en la respuesta reciente
Si su consulta solo consiste $where
operador $where
, puede pasar solo la expresión de JavaScript:
db.T.find("this.Grade1 > this.Grade2");
Para un mayor rendimiento, ejecute una operación agregada que tenga una canalización $redact
para filtrar los documentos que satisfagan la condición dada.
La tubería de $redact
incorpora la funcionalidad de $project
y $match
para implementar la redacción a nivel de campo donde devolverá todos los documentos que coincidan con la condición usando $$KEEP
y eliminará de la tubería los resultados que no coincidan con la variable $$PRUNE
.
Al ejecutar la siguiente operación agregada, se filtran los documentos de manera más eficiente que usando $where
para colecciones grandes, ya que esto utiliza una única canalización y operadores MongoDB nativos, en lugar de evaluaciones de JavaScript con $where
, lo que puede ralentizar la consulta:
db.T.aggregate([
{
"$redact": {
"$cond": [
{ "$gt": [ "$Grade1", "$Grade2" ] },
"$$KEEP",
"$$PRUNE"
]
}
}
])
que es una versión más simplificada de la incorporación de las dos tuberías $project
y $match
:
db.T.aggregate([
{
"$project": {
"isGrade1Greater": { "$cmp": [ "$Grade1", "$Grade2" ] },
"Grade1": 1,
"Grade2": 1,
"OtherFields": 1,
...
}
},
{ "$match": { "isGrade1Greater": 1 } }
])
Con MongoDB 3.4 y más nuevo:
db.T.aggregate([
{
"$addFields": {
"isGrade1Greater": { "$cmp": [ "$Grade1", "$Grade2" ] }
}
},
{ "$match": { "isGrade1Greater": 1 } }
])