यहां मुख्य मामला यह है कि एक "पाठ" खोज परिणाम आम तौर पर क्वेरी में अन्य फ़िल्टर स्थितियों पर प्राथमिकता ले रहा है, और इस तरह "पाठ" घटक से "पहले" परिणाम प्राप्त करना आवश्यक हो जाता है, और फिर मूल रूप से "स्कैन" के लिए दस्तावेज़ में अन्य शर्तें।
इस प्रकार की खोज को टेक्स्ट खोज परिणामों के साथ "रेंज" या किसी भी प्रकार की "असमानता" मिलान स्थिति के साथ अनुकूलित करना मुश्किल हो सकता है, और इसका मुख्य कारण यह है कि MongoDB इस "विशेष" इंडेक्स प्रकार को कैसे संभालता है।
एक संक्षिप्त प्रदर्शन के लिए, निम्नलिखित बुनियादी सेटअप पर विचार करें:
db.texty.drop();
db.texty.insert([
{ "a": "a", "text": "something" },
{ "a": "b", "text": "something" },
{ "a": "b", "text": "nothing much" },
{ "a": "c", "text": "something" }
])
db.texty.createIndex({ "text": "text" })
db.texty.createIndex({ "a": 1 })
इसलिए यदि आप इसे टेक्स्ट खोज की स्थिति के साथ-साथ अन्य क्षेत्र ( { "$lt": "c" }
पर एक श्रेणी विचार के साथ देखना चाहते हैं। ), तो आप इस प्रकार संभाल सकते हैं:
db.texty.find({ "a": { "$lt": "c" }, "$text": { "$search": "something" } }).explain()
व्याख्या आउटपुट के साथ जैसे (महत्वपूर्ण भाग):
"winningPlan" : {
"stage" : "FETCH",
"filter" : {
"a" : {
"$lt" : "c"
}
},
"inputStage" : {
"stage" : "TEXT",
"indexPrefix" : {
},
"indexName" : "text_text",
"parsedTextQuery" : {
"terms" : [
"someth"
],
"negatedTerms" : [ ],
"phrases" : [ ],
"negatedPhrases" : [ ]
},
"inputStage" : {
"stage" : "TEXT_MATCH",
"inputStage" : {
"stage" : "TEXT_OR",
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"_fts" : "text",
"_ftsx" : 1
},
"indexName" : "text_text",
"isMultiKey" : true,
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 1,
"direction" : "backward",
"indexBounds" : {
}
}
}
}
}
},
जो मूल रूप से "पहले . कह रहा है मुझे पाठ परिणाम प्राप्त करें और फिर उन परिणामों को दूसरी शर्त के अनुसार फ़िल्टर करें" . तो स्पष्ट रूप से यहां केवल "टेक्स्ट" इंडेक्स का उपयोग किया जा रहा है और फिर इसके द्वारा लौटाए गए सभी परिणामों को बाद में सामग्री की जांच करके फ़िल्टर किया जा रहा है।
यह दो कारणों से इष्टतम नहीं है, क्योंकि यह हो सकता है कि टेक्स्ट खोज से मेल खाने के बजाय डेटा "रेंज" स्थिति से सबसे अच्छी तरह से बाधित हो। दूसरे, अन्य डेटा पर एक इंडेक्स होने के बावजूद, इसका उपयोग यहां तुलना के लिए नहीं किया जा रहा है। इसलिए प्रत्येक परिणाम के लिए संपूर्ण दस्तावेज़ लोड किया जाता है और फ़िल्टर का परीक्षण किया जाता है।
फिर आप यहां "यौगिक" अनुक्रमणिका प्रारूप पर विचार कर सकते हैं, और यह प्रारंभ में तार्किक प्रतीत होगा कि यदि "श्रेणी" चयन के लिए अधिक विशिष्ट है, तो उसे अनुक्रमित कुंजियों के उपसर्ग क्रम के रूप में शामिल करें:
db.texty.dropIndexes();
db.texty.createIndex({ "a": 1, "text": "text" })
लेकिन यहाँ एक पकड़ है, जब से आप क्वेरी को फिर से चलाने का प्रयास करते हैं:
db.texty.find({ "a": { "$lt": "c" }, "$text": { "$search": "something" } })
इसके परिणामस्वरूप एक त्रुटि होगी:
<ब्लॉकक्वॉट>त्रुटि:त्रुटि:{"प्रतीक्षित MS":NumberLong(0),"ok":0,"errmsg":"त्रुटि प्रसंस्करण क्वेरी:ns=test.textyTree:$and\n a $lt \"c\"\n पाठ:query=something, language=english, caseSensitive=0, diacriticSensitive=0, tag=NULL\nसॉर्ट:{}\nProj:{}\n प्लानर ने एरर लौटाया:$text क्वेरी को संतुष्ट करने के लिए टेक्स्ट इंडेक्स का उपयोग करने में विफल रहा (यदि टेक्स्ट इंडेक्स है कंपाउंड, क्या समता विधेय सभी उपसर्ग क्षेत्रों के लिए दिए गए हैं?)","code" :2}
तो भले ही यह "इष्टतम" लग सकता है, जिस तरह से MongoDB विशेष "पाठ" अनुक्रमणिका के लिए क्वेरी (और वास्तव में अनुक्रमणिका चयन) को संसाधित करता है, सीमा के बाहर इस "बहिष्करण" के लिए संभव नहीं है।पी>
हालांकि आप इस पर "समानता" मैच बहुत ही कुशल तरीके से कर सकते हैं:
db.texty.find({ "a": "b", "$text": { "$search": "something" } }).explain()
व्याख्या आउटपुट के साथ:
"winningPlan" : {
"stage" : "TEXT",
"indexPrefix" : {
"a" : "b"
},
"indexName" : "a_1_text_text",
"parsedTextQuery" : {
"terms" : [
"someth"
],
"negatedTerms" : [ ],
"phrases" : [ ],
"negatedPhrases" : [ ]
},
"inputStage" : {
"stage" : "TEXT_MATCH",
"inputStage" : {
"stage" : "TEXT_OR",
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"a" : 1,
"_fts" : "text",
"_ftsx" : 1
},
"indexName" : "a_1_text_text",
"isMultiKey" : true,
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 1,
"direction" : "backward",
"indexBounds" : {
}
}
}
}
},
तो सूचकांक का उपयोग किया जाता है और इसे अन्य शर्त के आउटपुट से मेल खाने वाले टेक्स्ट को प्रदान की गई सामग्री को "पूर्व-फ़िल्टर" करने के लिए दिखाया जा सकता है।
यदि वास्तव में आप खोज के लिए "उपसर्ग" को "पाठ" फ़ील्ड के रूप में अनुक्रमणिका में रखते हैं:
db.texty.dropIndexes();
db.texty.createIndex({ "text": "text", "a": 1 })
फिर खोज करें:
db.texty.find({ "a": { "$lt": "c" }, "$text": { "$search": "something" } }).explain()
फिर आप उपरोक्त "समानता" मिलान के समान परिणाम देखते हैं:
"winningPlan" : {
"stage" : "TEXT",
"indexPrefix" : {
},
"indexName" : "text_text_a_1",
"parsedTextQuery" : {
"terms" : [
"someth"
],
"negatedTerms" : [ ],
"phrases" : [ ],
"negatedPhrases" : [ ]
},
"inputStage" : {
"stage" : "TEXT_MATCH",
"inputStage" : {
"stage" : "TEXT_OR",
"filter" : {
"a" : {
"$lt" : "c"
}
},
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"_fts" : "text",
"_ftsx" : 1,
"a" : 1
},
"indexName" : "text_text_a_1",
"isMultiKey" : true,
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 1,
"direction" : "backward",
"indexBounds" : {
}
}
}
}
},
पहले प्रयास से यहां बड़ा अंतर यह है कि filter
प्रसंस्करण श्रृंखला में रखा गया है, यह दर्शाता है कि "उपसर्ग" मिलान नहीं (जो कि सबसे इष्टतम है), सामग्री को वास्तव में "पाठ" चरण में भेजे जाने से पहले "पहले" सूचकांक से स्कैन किया जा रहा है।
तो यह "पूर्व-फ़िल्टर्ड" है, लेकिन निश्चित रूप से सबसे इष्टतम तरीके से नहीं है, और यह "टेक्स्ट" इंडेक्स का उपयोग करने की प्रकृति के कारण है। तो अगर आप सिर्फ एक इंडेक्स पर प्लेन रेंज को अपने आप मानते हैं:
db.texty.createIndex({ "a": 1 })
db.texty.find({ "a": { "$lt": "c" } }).explain()
फिर व्याख्या आउटपुट:
"winningPlan" : {
"stage" : "FETCH",
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"a" : 1
},
"indexName" : "a_1",
"isMultiKey" : false,
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 1,
"direction" : "forward",
"indexBounds" : {
"a" : [
"[\"\", \"c\")"
]
}
}
},
फिर उसे कम से कम indexBounds
. मिल गया इंडेक्स के केवल उस हिस्से पर विचार करने और देखने के लिए जो उस सीमा के भीतर आता है।
तो यहाँ यही अंतर है। "यौगिक" संरचना का उपयोग करने से आपको चयन को कम करने में सक्षम होने के कारण यहां कुछ पुनरावृत्ति चक्रों को सहेजना चाहिए, लेकिन इसे अभी भी सभी अनुक्रमणिका प्रविष्टियों को फ़िल्टर करने के लिए स्कैन करना होगा, और निश्चित रूप से नहीं होना चाहिए अनुक्रमणिका में "उपसर्ग" तत्व बनें, जब तक कि आप उस पर एक समानता मिलान का उपयोग नहीं कर सकते।
अनुक्रमणिका में एक यौगिक संरचना के बिना, आप हमेशा "पहले" पाठ परिणाम लौटा रहे हैं, और फिर उन परिणामों के लिए कोई अन्य शर्तें लागू कर रहे हैं। साथ ही क्वेरी इंजन हैंडलिंग के कारण "टेक्स्ट" इंडेक्स और "सामान्य" इंडेक्स को देखने से परिणामों को "गठबंधन/प्रतिच्छेद" करना संभव नहीं है। यह आम तौर पर इष्टतम दृष्टिकोण नहीं होने वाला है, इसलिए विचारों की योजना बनाना महत्वपूर्ण है।
संक्षेप में, "समानता" मिलान "उपसर्ग" के साथ आदर्श रूप से मिश्रित, और यदि नहीं तो पाठ परिभाषा के "बाद" अनुक्रमणिका में शामिल करें।