T
2 alanlı bir koleksiyonum var : Grade1
ve Grade2
koşullu olanları seçmek Grade1 > Grade2
istiyorum, MySQL'deki gibi bir sorguyu nasıl alabilirim?
Select * from T Where Grade1 > Grade2
T
2 alanlı bir koleksiyonum var : Grade1
ve Grade2
koşullu olanları seçmek Grade1 > Grade2
istiyorum, MySQL'deki gibi bir sorguyu nasıl alabilirim?
Select * from T Where Grade1 > Grade2
Yanıtlar:
$ Nerede kullanabilirsiniz. Sadece oldukça yavaş olacağını unutmayın (her kayıtta Javascript kodu çalıştırması gerekir), bu yüzden eğer yapabiliyorsanız indekslenmiş sorgularla birleştirin.
db.T.find( { $where: function() { return this.Grade1 > this.Grade2 } } );
veya daha kompakt:
db.T.find( { $where : "this.Grade1 > this.Grade2" } );
son cevapta$expr
açıklandığı gibi kullanabilirsiniz
$where: function() { return this.Grade1 - this.Grade2 > variable }
?
db.T.find({$where: function() {return this.startDate == ISODate("2017-01-20T10:55:08.000Z");}});
hiçbir şey döndürmüyor, koleksiyondaki doktorlardan biri bile ISODate("2017-01-20T10:55:08.000Z")
. Ama <=
ve >=
iş gibi görünüyor. Herhangi bir fikir?
this.startDate.getTime() == ISODate("2017-01-20T10:55:08.000Z").getTime()
Normal sorguda toplama işlevlerini kullanmak için $ ifade (3.6 mongo sürüm operatörü) kullanabilirsiniz.
Karşılaştırma query operators
vs aggregation comparison operators
.
Normal Sorgu:
db.T.find({$expr:{$gt:["$Grade1", "$Grade2"]}})
Toplama Sorgusu:
db.T.aggregate({$match:{$expr:{$gt:["$Grade1", "$Grade2"]}}})
Sorgunuz yalnızca $where
operatörden oluşuyorsa, yalnızca JavaScript ifadesini iletebilirsiniz:
db.T.find("this.Grade1 > this.Grade2");
Daha yüksek performans için, $redact
verilen koşulu karşılayan belgeleri filtrelemek için bir ardışık düzen içeren bir toplu işlem çalıştırın .
$redact
Boru hattı işlevselliğini içerir $project
ve $match
bunun kullanarak durumu uyan tüm belgeleri döndürecektir saha seviyesi redaksiyon uygulamak için $$KEEP
boru hattı sonuçlarından kullanarak eşleşmiyor olanlar ve kaldırır $$PRUNE
değişkeni.
Aşağıdaki toplu işlem filtresini çalıştırmak, belgeleri $where
büyük koleksiyonlar için kullanmaktan daha verimli bir şekilde filtrelemektedir, çünkü bu $where
, sorguyu yavaşlatabilen JavaScript değerlendirmelerinden ziyade tek bir ardışık düzen ve yerel MongoDB işleçlerini kullanır :
db.T.aggregate([
{
"$redact": {
"$cond": [
{ "$gt": [ "$Grade1", "$Grade2" ] },
"$$KEEP",
"$$PRUNE"
]
}
}
])
hangi iki boru hattının birleşmeyle daha basitleştirilmiş bir versiyonudur $project
ve $match
:
db.T.aggregate([
{
"$project": {
"isGrade1Greater": { "$cmp": [ "$Grade1", "$Grade2" ] },
"Grade1": 1,
"Grade2": 1,
"OtherFields": 1,
...
}
},
{ "$match": { "isGrade1Greater": 1 } }
])
İle MongoDB 3.4 ve daha yeni:
db.T.aggregate([
{
"$addFields": {
"isGrade1Greater": { "$cmp": [ "$Grade1", "$Grade2" ] }
}
},
{ "$match": { "isGrade1Greater": 1 } }
])
Performans okunabilirlikten daha önemliyse ve koşulunuz basit aritmetik işlemlerden oluştuğu sürece toplama işlem hattını kullanabilirsiniz. İlk olarak, koşulun sol tarafını hesaplamak için $ project kullanın (tüm alanları sol tarafa alın). Daha sonra bir sabitle karşılaştırmak ve filtrelemek için $ match kullanın. Bu şekilde javascript yürütmesini engellersiniz. Aşağıda python'daki testim:
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)
Toplam kullanarak:
%timeit -n1 -r1 list(coll.aggregate([
{
'$project': {
'diff': {'$subtract': ['$Grade1', '$Grade2']},
'Grade1': 1,
'Grade2': 1
}
},
{
'$match': {'diff': {'$gt': 0}}
}
]))
1 döngü, döngü başına en iyi 1: 192 ms
Find ve $ where kullanarak:
%timeit -n1 -r1 list(coll.find({'$where': 'this.Grade1 > this.Grade2'}))
1 döngü, döngü başına en iyi 1: 4,54 sn