मेरे पास T
2 फ़ील्ड के साथ एक संग्रह है : Grade1
और Grade2
, और मैं शर्त के साथ उन लोगों का चयन करना चाहता Grade1 > Grade2
हूं, जिन्हें MySQL में एक क्वेरी कैसे मिल सकती है?
Select * from T Where Grade1 > Grade2
मेरे पास T
2 फ़ील्ड के साथ एक संग्रह है : Grade1
और Grade2
, और मैं शर्त के साथ उन लोगों का चयन करना चाहता Grade1 > Grade2
हूं, जिन्हें MySQL में एक क्वेरी कैसे मिल सकती है?
Select * from T Where Grade1 > Grade2
जवाबों:
आप $ का उपयोग कहां कर सकते हैं। बस जागरूक रहें यह काफी धीमा होगा (प्रत्येक रिकॉर्ड पर जावास्क्रिप्ट कोड निष्पादित करना होगा) इसलिए यदि आप कर सकते हैं तो अनुक्रमित प्रश्नों के साथ गठबंधन करें।
db.T.find( { $where: function() { return this.Grade1 > this.Grade2 } } );
या अधिक कॉम्पैक्ट:
db.T.find( { $where : "this.Grade1 > this.Grade2" } );
आप हाल के उत्तर$expr
में वर्णित अनुसार उपयोग कर सकते हैं
$where: function() { return this.Grade1 - this.Grade2 > variable }
?
db.T.find({$where: function() {return this.startDate == ISODate("2017-01-20T10:55:08.000Z");}});
कि यह कुछ भी नहीं लौटाए, यहां तक कि संग्रह में डॉक्टर में से एक भी है ISODate("2017-01-20T10:55:08.000Z")
। लेकिन <=
और >=
काम लगता है। कोई उपाय?
this.startDate.getTime() == ISODate("2017-01-20T10:55:08.000Z").getTime()
नियमित क्वेरी में एकत्रीकरण कार्यों का उपयोग करने के लिए आप $ expr (3.6 mongo संस्करण ऑपरेटर) का उपयोग कर सकते हैं ।
query operators
बनाम की तुलना करें aggregation comparison operators
।
नियमित क्वेरी:
db.T.find({$expr:{$gt:["$Grade1", "$Grade2"]}})
एकत्रीकरण क्वेरी:
db.T.aggregate({$match:{$expr:{$gt:["$Grade1", "$Grade2"]}}})
यदि आपकी क्वेरी में केवल $where
ऑपरेटर शामिल हैं, तो आप केवल जावास्क्रिप्ट अभिव्यक्ति में पास कर सकते हैं:
db.T.find("this.Grade1 > this.Grade2");
अधिक प्रदर्शन के लिए, एक समग्र ऑपरेशन चलाएं $redact
जिसमें दस्तावेज़ों को फ़िल्टर करने के लिए एक पाइपलाइन है जो दी गई स्थिति को पूरा करता है।
$redact
पाइप लाइन की कार्यक्षमता को शामिल किया गया $project
और $match
क्षेत्र स्तर संपादकत्व जहां यह हालत मिलान का उपयोग कर सभी दस्तावेजों वापस आ जाएगी लागू करने के लिए $$KEEP
उन है कि का उपयोग कर से मेल नहीं खाते और पाइपलाइन परिणामों से निकाल देता $$PRUNE
चर।
निम्नलिखित एकत्रीकरण ऑपरेशन को चलाना $where
बड़े संग्रह के लिए उपयोग करने की तुलना में अधिक कुशलता से दस्तावेजों को फ़िल्टर करता है क्योंकि यह जावास्क्रिप्ट मूल्यांकन के बजाय एक एकल पाइपलाइन और देशी मोंगोडीबी ऑपरेटरों का उपयोग करता है $where
, जो क्वेरी को धीमा कर सकता है:
db.T.aggregate([
{
"$redact": {
"$cond": [
{ "$gt": [ "$Grade1", "$Grade2" ] },
"$$KEEP",
"$$PRUNE"
]
}
}
])
जो दो पाइपलाइनों को शामिल करने का अधिक सरलीकृत संस्करण है $project
और $match
:
db.T.aggregate([
{
"$project": {
"isGrade1Greater": { "$cmp": [ "$Grade1", "$Grade2" ] },
"Grade1": 1,
"Grade2": 1,
"OtherFields": 1,
...
}
},
{ "$match": { "isGrade1Greater": 1 } }
])
साथ MongoDB 3.4 और नए:
db.T.aggregate([
{
"$addFields": {
"isGrade1Greater": { "$cmp": [ "$Grade1", "$Grade2" ] }
}
},
{ "$match": { "isGrade1Greater": 1 } }
])
मामले में प्रदर्शन पठनीयता से अधिक महत्वपूर्ण है और जब तक आपकी स्थिति में सरल अंकगणितीय ऑपरेशन होते हैं, आप एकत्रीकरण पाइपलाइन का उपयोग कर सकते हैं। पहले, बाएं हाथ की स्थिति की गणना करने के लिए $ परियोजना का उपयोग करें (सभी क्षेत्रों को बाएं हाथ की ओर ले जाएं)। फिर एक स्थिर और फिल्टर के साथ तुलना करने के लिए $ मैच का उपयोग करें। इस तरह आप जावास्क्रिप्ट निष्पादन से बचते हैं। नीचे अजगर में मेरा परीक्षण है:
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)
कुल का उपयोग करना:
%timeit -n1 -r1 list(coll.aggregate([
{
'$project': {
'diff': {'$subtract': ['$Grade1', '$Grade2']},
'Grade1': 1,
'Grade2': 1
}
},
{
'$match': {'diff': {'$gt': 0}}
}
]))
1 लूप, सर्वश्रेष्ठ 1: 192 एमएस प्रति लूप
खोज और $ का उपयोग करके जहां:
%timeit -n1 -r1 list(coll.find({'$where': 'this.Grade1 > this.Grade2'}))
1 लूप, सर्वश्रेष्ठ 1: 4.54 प्रति लूप