Ich habe eine Sammlung T
mit 2 Feldern: Grade1
und Grade2
, und ich möchte diejenigen mit Bedingung auswählen Grade1 > Grade2
, wie kann ich eine Abfrage wie in MySQL erhalten?
Select * from T Where Grade1 > Grade2
Ich habe eine Sammlung T
mit 2 Feldern: Grade1
und Grade2
, und ich möchte diejenigen mit Bedingung auswählen Grade1 > Grade2
, wie kann ich eine Abfrage wie in MySQL erhalten?
Select * from T Where Grade1 > Grade2
Antworten:
Sie können ein $ where verwenden. Beachten Sie jedoch, dass es ziemlich langsam sein wird (Javascript-Code muss für jeden Datensatz ausgeführt werden). Kombinieren Sie es daher mit indizierten Abfragen, wenn Sie können.
db.T.find( { $where: function() { return this.Grade1 > this.Grade2 } } );
oder kompakter:
db.T.find( { $where : "this.Grade1 > this.Grade2" } );
Sie können $expr
wie in der letzten Antwort beschrieben verwenden
$where: function() { return this.Grade1 - this.Grade2 > variable }
?
db.T.find({$where: function() {return this.startDate == ISODate("2017-01-20T10:55:08.000Z");}});
es nichts zurück, sogar eines der Dokumente in der Sammlung ist ISODate("2017-01-20T10:55:08.000Z")
. Aber <=
und >=
scheinen Arbeit. irgendeine Idee?
this.startDate.getTime() == ISODate("2017-01-20T10:55:08.000Z").getTime()
Sie können $ expr (3.6 Mongo-Versionsoperator) verwenden, um Aggregationsfunktionen in regulären Abfragen zu verwenden.
Vergleichen query operators
vs aggregation comparison operators
.
Regelmäßige Abfrage:
db.T.find({$expr:{$gt:["$Grade1", "$Grade2"]}})
Aggregationsabfrage:
db.T.aggregate({$match:{$expr:{$gt:["$Grade1", "$Grade2"]}}})
Wenn Ihre Abfrage nur aus dem $where
Operator besteht, können Sie nur den JavaScript-Ausdruck übergeben:
db.T.find("this.Grade1 > this.Grade2");
Führen Sie für eine höhere Leistung eine Aggregatoperation mit einer $redact
Pipeline aus, um die Dokumente zu filtern, die die angegebene Bedingung erfüllen.
Die $redact
Pipeline enthält die Funktionalität von $project
und $match
zum Implementieren von Redaktionen auf Feldebene, bei denen alle Dokumente zurückgegeben werden, die der Bedingung entsprechen, $$KEEP
und diejenigen aus der Pipeline entfernt werden, die nicht mit der $$PRUNE
Variablen übereinstimmen.
Durch Ausführen der folgenden Aggregatoperation werden die Dokumente effizienter gefiltert als $where
für große Sammlungen, da hierfür eine einzelne Pipeline und native MongoDB-Operatoren anstelle von JavaScript-Auswertungen verwendet werden $where
, wodurch die Abfrage verlangsamt werden kann:
db.T.aggregate([
{
"$redact": {
"$cond": [
{ "$gt": [ "$Grade1", "$Grade2" ] },
"$$KEEP",
"$$PRUNE"
]
}
}
])
Dies ist eine vereinfachte Version der Integration der beiden Pipelines $project
und $match
:
db.T.aggregate([
{
"$project": {
"isGrade1Greater": { "$cmp": [ "$Grade1", "$Grade2" ] },
"Grade1": 1,
"Grade2": 1,
"OtherFields": 1,
...
}
},
{ "$match": { "isGrade1Greater": 1 } }
])
Mit MongoDB 3.4 und neuer:
db.T.aggregate([
{
"$addFields": {
"isGrade1Greater": { "$cmp": [ "$Grade1", "$Grade2" ] }
}
},
{ "$match": { "isGrade1Greater": 1 } }
])
Wenn die Leistung wichtiger ist als die Lesbarkeit und Ihre Bedingung aus einfachen arithmetischen Operationen besteht, können Sie die Aggregationspipeline verwenden. Verwenden Sie zuerst $ project, um die linke Seite der Bedingung zu berechnen (nehmen Sie alle Felder auf die linke Seite). Verwenden Sie dann $ match, um mit einer Konstante und einem Filter zu vergleichen. Auf diese Weise vermeiden Sie die Ausführung von Javascript. Unten ist mein Test in 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)
Aggregat verwenden:
%timeit -n1 -r1 list(coll.aggregate([
{
'$project': {
'diff': {'$subtract': ['$Grade1', '$Grade2']},
'Grade1': 1,
'Grade2': 1
}
},
{
'$match': {'diff': {'$gt': 0}}
}
]))
1 Schleife, am besten 1: 192 ms pro Schleife
Mit find und $ where:
%timeit -n1 -r1 list(coll.find({'$where': 'this.Grade1 > this.Grade2'}))
1 Schleife, am besten 1: 4,54 s pro Schleife