त्वरित समाधान
आपकी "पाइपलाइन" यहां काम नहीं करती है मुख्य रूप से क्योंकि आपका प्रारंभिक $project
उस क्षेत्र की कमी है जिसे आप बाद के चरण में उपयोग करना चाहते हैं। "त्वरित समाधान" इसलिए मूल रूप से उस फ़ील्ड को "अनुमानित" दस्तावेज़ में शामिल करना है, क्योंकि इस तरह से एकत्रीकरण पाइपलाइन चरण काम करते हैं:
array(
array(
'$project' => array(
'FullName' => array('$concat' => array('$first_name', ' ', '$middle_name', ' ', '$last_name')),
'FirstMiddle' => array('$concat' => array('$first_name', ' ', '$middle_name')),
'FirstLast' => array('$concat' => array('$first_name', ' ', '$last_name')),
'FirstName' => array('$concat' => array('$first_name')),
'MiddleName' => array('$concat' => array('$middle_name')),
'LastName' => array('$concat' => array('$last_name')),
'Student' => '$$ROOT',
'allotment_details' => 1 # that's the change
)
),
या जब से आपने $$ROOT
. का उपयोग किया है विद्यार्थी
. के लिए वैसे भी, बस उस पथ के तहत क्षेत्र को अर्हता प्राप्त करें:
'$expr' => array(
'$eq'=> array(
array('$arrayElemAt' => array('$Student.allotment_details.room_id', -1)),
$this->RoomId
)
),
हालांकि मैं दृढ़ता से* आपसे निवेदन है कि आप नहीं . करें ऐसा करो।
बाद में $मिलान
सामग्री पर वास्तव में एक बुरा विचार है क्योंकि इसका मतलब है कि किसी भी "फ़िल्टरिंग" के वास्तव में पूरा होने से पहले पूरे संग्रह को पाइपलाइन में फिर से लिखा जाता है।
इसी तरह "अंतिम" सरणी तत्व पर मिलान करना भी एक मुद्दा है। इसके बजाय वास्तव में "नए आइटम" को "अंत" के बजाय सरणी की "शुरुआत" में जोड़ना एक बेहतर तरीका है। यह वास्तव में $position
है
या संभवतः यहां तक कि $सॉर्ट
$push
में संशोधक
आपके लिए करते हैं, जहां आइटम जोड़े जाते हैं या आइटमों का क्रमबद्ध क्रम क्रमशः बदलकर।
ऐरे को "नवीनतम पहले" में बदलना
चीजों को स्टोर करने के आपके तरीके को बदलकर यह थोड़ा काम लेता है, लेकिन लाभ ऐसे प्रश्नों की गति में काफी सुधार हुआ है जैसे आप मूल्यांकन किए बिना $expr
चाहते हैं तर्क।
मूल अवधारणाएं सिंटैक्स के साथ नए सरणी आइटम को "प्री-पेंड" करना है जैसे:
$this->collection->updateOne(
$query,
[ '$push' => [ 'allotment_details' => [ '$each' => $allotments, '$position' => 0 ] ] ]
)
जहां $आवंटियां
होना चाहिए $each
द्वारा आवश्यकतानुसार एक सरणी बनें
और $position
0
. के लिए प्रयोग किया जाता है नया सरणी आइटम "पहले" जोड़ने के लिए।
वैकल्पिक रूप से यदि आपके पास वास्तव में created_date
. जैसा कुछ है सरणी में प्रत्येक ऑब्जेक्ट के भीतर एक संपत्ति के रूप में, तो आप $सॉर्ट करें
इसके बजाय एक संशोधक के रूप में।
$this->collection->updateOne(
$query,
[ '$push' => [
'allotment_details' => [ '$each' => $allotments, '$sort' => [ 'created_date' => -1 ] ]
]]
)
यह वास्तव में इस बात पर निर्भर करता है कि आपकी "क्वेरी" और अन्य एक्सेस आवश्यकताएं "अंतिम जोड़ी" या "नवीनतम तिथि" पर निर्भर करती हैं, और फिर आम तौर पर यदि आप संभवतः ऐसे created_date
को बदलने का इरादा रखते हैं या अन्य "सॉर्ट" संपत्ति इस तरह से जो "क्रमबद्ध" होने पर सरणी तत्वों के क्रम को प्रभावित करेगी।
ऐसा करने का कारण यह है कि सरणी में "नवीनतम" (जो अब "पहला" है) आइटम से मेल खाता है:
$this->collection->find([
'allotment_details.0.room_id': $this->RoomId
])
MongoDB "पहले" सरणी अनुक्रमणिका को "Dot Notation" के साथ निर्दिष्ट करने की अनुमति देता है।
, 0
. का उपयोग करके अनुक्रमणिका। आप क्या नहीं कर सकते हैं do एक "नकारात्मक" अनुक्रमणिका निर्दिष्ट करता है अर्थात:
$this->collection->find([
'allotment_details.-1.room_id': $this->RoomId # not allowed :(
])
यही कारण है कि आप अपने सरणी को व्यावहारिक रूप में "पुनः क्रमित" करने के लिए "अपडेट" पर ऊपर दिखाए गए काम करते हैं।
संयोजन खराब है
अन्य मुख्य मुद्दा तारों का संयोजन है। जैसा कि पहले ही उल्लेख किया गया है, यह आपके इच्छित मिलान करने के लिए अनावश्यक ओवरहेड बनाता है। यह "अनावश्यक" भी है क्योंकि आप $या
. का उपयोग करके इससे बच सकते हैं प्रत्येक फ़ील्ड पर शर्तों के साथ क्योंकि वे वास्तविक दस्तावेज़ में पहले से मौजूद हैं:
$this->collection->find([
'$or' => [
[ 'first_name' => new MongoDB\BSON\Regex($arg, 'i') ],
[ 'last_name' => new MongoDB\BSON\Regex($arg, 'i') ],
[ 'middle_name' => new MongoDB\BSON\Regex($arg, 'i') ],
[ 'registration_temp_perm_no' => $arg ]
],
'schoolId' => new MongoDB\BSON\ObjectID($this->SchoolId),
'allotment_details.0.room_id': $this->RoomId
])
और निश्चित रूप से "पूर्ण" क्वेरी शर्तों को वास्तव में जो भी होना चाहिए, लेकिन आपको मूल विचार प्राप्त करना चाहिए।
इसके अलावा, यदि आप वास्तव में "आंशिक शब्दों" की तलाश नहीं कर रहे हैं, तो एक "text search"ए> "नाम" वाले क्षेत्रों में परिभाषित किया गया है। इंडेक्स बनाने के बाद जो होगा:
$this->collection->find([
'$text' => [ '$search' => $arg ],
'schoolId' => new MongoDB\BSON\ObjectID($this->SchoolId),
'allotment_details.0.room_id': $this->RoomId
])
कुल मिलाकर मैं वास्तव में आपके मौजूदा कोड में एक छोटा सा बदलाव करने के बजाय अन्य सभी विकल्पों को करीब से देखने की सलाह दूंगा। आप चीजों को कैसे स्टोर करते हैं और वास्तव में "इंडेक्स" चीजों की थोड़ी सावधानीपूर्वक पुनर्संरचना के साथ, आपको विशाल प्रदर्शन लाभ मिलते हैं जो आपके व्यापक $concat
"क्रूर बल" दृष्टिकोण बस वितरित नहीं कर सकता।