तो arrayFilters स्थितीय फ़िल्टर के साथ विकल्प $[<identifier>] मोंगोडीबी 3.5.12 के बाद से विकास रिलीज श्रृंखला के साथ वास्तव में ठीक से काम करता है और मोंगोडीबी 3.6 श्रृंखला के लिए वर्तमान रिलीज उम्मीदवारों में भी, जहां यह वास्तव में आधिकारिक तौर पर जारी किया जाएगा। एकमात्र समस्या यह है कि उपयोग में आने वाले "ड्राइवर" वास्तव में अभी तक इसे नहीं पकड़ पाए हैं।
उसी सामग्री को फिर से दोहराना जो मैंने पहले से ही MongoDB के साथ नेस्टेड ऐरे को अपडेट करने पर रखा है:
<ब्लॉकक्वॉट>
नोट कुछ हद तक विडंबना यह है कि यह .update() के लिए "विकल्प" तर्क में निर्दिष्ट है। और विधियों की तरह, सिंटैक्स आम तौर पर सभी हाल के रिलीज़ ड्राइवर संस्करणों के साथ संगत है।
हालांकि यह mongo . के बारे में सच नहीं है खोल, जिस तरह से वहां विधि लागू की गई है ("विडंबना यह है कि पिछड़े संगतता के लिए") arrayFilters तर्क को एक आंतरिक विधि द्वारा पहचाना और हटाया नहीं जाता है जो पिछले MongoDB सर्वर संस्करणों और "विरासत" .update() के साथ "पिछड़ा संगतता" देने के लिए विकल्पों को पार्स करता है। एपीआई कॉल सिंटैक्स।
इसलिए यदि आप mongo . में कमांड का उपयोग करना चाहते हैं शेल या अन्य "खोल आधारित" उत्पाद (विशेषकर रोबो 3T) आपको विकास शाखा से नवीनतम संस्करण या 3.6 या उससे अधिक के उत्पादन रिलीज की आवश्यकता है।
इसका मतलब यह है कि .update() . का वर्तमान "ड्राइवर" कार्यान्वयन वास्तव में arrayFilters . की परिभाषा के साथ आवश्यक तर्कों को "हटा" देता है . NodeJS के लिए इसे ड्राइवर की 3.x रिलीज़ श्रृंखला में संबोधित किया जाएगा, और निश्चित रूप से "मोंगोज़" को उस रिलीज़ के बाद अपडेट किए गए ड्राइवर पर अपनी निर्भरता को लागू करने में कुछ समय लगेगा, जो अब "स्ट्रिप" नहीं होगा। ऐसी कार्रवाइयां।
हालांकि आप इसे अभी भी समर्थित . पर चला सकते हैं सर्वर इंस्टेंस, मूल "अपडेट कमांड" सिंटैक्स उपयोग को वापस छोड़कर, क्योंकि यह कार्यान्वित ड्राइवर विधि को छोड़ देता है:
const mongoose = require('mongoose'),
Schema = mongoose.Schema,
ObjectId = mongoose.Types.ObjectId;
mongoose.Promise = global.Promise;
mongoose.set('debug',true);
const uri = 'mongodb://localhost/test',
options = { useMongoClient: true };
const contactSchema = new Schema({
data: String,
type: String,
priority: String,
retries: String
});
const personSchema = new Schema({
name: String,
level: String,
priority: String,
enabled: Boolean,
contacts: [contactSchema]
});
const groupSchema = new Schema({
name: String,
people: [personSchema],
workingHours: { start: String, end: String },
workingDays: { type: [Number], default: undefined },
contactTypes: {
workingHours: { type: [String], default: undefined },
contactTypes: { type: [String], default: undefined }
}
});
const Group = mongoose.model('Group', groupSchema);
function log(data) {
console.log(JSON.stringify(data, undefined, 2))
}
(async function() {
try {
const conn = await mongoose.connect(uri,options);
// Clean data
await Promise.all(
Object.entries(conn.models).map(([k,m]) => m.remove() )
);
// Create sample
await Group.create({
name: "support",
people: [
{
"_id": ObjectId("5a05a8c3e0ce3444f8ec5bd8"),
"enabled": true,
"level": "1",
"name": "Someone",
"contacts": [
{
"type": "email",
"data": "example@sqldat.com"
},
{
"_id": ObjectId("5a05a8dee0ce3444f8ec5bda"),
"retries": "1",
"priority": "1",
"type": "email",
"data": "example@sqldat.com"
}
]
}
]
});
let result = await conn.db.command({
"update": Group.collection.name,
"updates": [
{
"q": {},
"u": { "$set": { "people.$[i].contacts.$[j].data": "new data" } },
"multi": true,
"arrayFilters": [
{ "i._id": ObjectId("5a05a8c3e0ce3444f8ec5bd8") },
{ "j._id": ObjectId("5a05a8dee0ce3444f8ec5bda") }
]
}
]
});
log(result);
let group = await Group.findOne();
log(group);
} catch(e) {
console.error(e);
} finally {
mongoose.disconnect();
}
})()
चूंकि यह "कमांड" को सीधे सर्वर के माध्यम से भेजता है, हम देखते हैं कि अपेक्षित अपडेट वास्तव में होता है:
Mongoose: groups.remove({}, {})
Mongoose: groups.insert({ name: 'support', _id: ObjectId("5a06557fb568aa0ad793c5e4"), people: [ { _id: ObjectId("5a05a8c3e0ce3444f8ec5bd8"), enabled: true, level: '1', name: 'Someone', contacts: [ { type: 'email', data: 'example@sqldat.com', _id: ObjectId("5a06557fb568aa0ad793c5e5") }, { _id: ObjectId("5a05a8dee0ce3444f8ec5bda"), retries: '1', priority: '1', type: 'email', data: 'example@sqldat.com' } ] } ], __v: 0 })
{ n: 1,
nModified: 1,
opTime:
{ ts: Timestamp { _bsontype: 'Timestamp', low_: 3, high_: 1510364543 },
t: 24 },
electionId: 7fffffff0000000000000018,
ok: 1,
operationTime: Timestamp { _bsontype: 'Timestamp', low_: 3, high_: 1510364543 },
'$clusterTime':
{ clusterTime: Timestamp { _bsontype: 'Timestamp', low_: 3, high_: 1510364543 },
signature: { hash: [Object], keyId: 0 } } }
Mongoose: groups.findOne({}, { fields: {} })
{
"_id": "5a06557fb568aa0ad793c5e4",
"name": "support",
"__v": 0,
"people": [
{
"_id": "5a05a8c3e0ce3444f8ec5bd8",
"enabled": true,
"level": "1",
"name": "Someone",
"contacts": [
{
"type": "email",
"data": "example@sqldat.com",
"_id": "5a06557fb568aa0ad793c5e5"
},
{
"_id": "5a05a8dee0ce3444f8ec5bda",
"retries": "1",
"priority": "1",
"type": "email",
"data": "new data" // <-- updated here
}
]
}
]
}
तो ठीक है "अभी" "ऑफ़ द शेल्फ़" उपलब्ध ड्राइवर वास्तव में .update() . को लागू नहीं करते हैं या यह अन्य कार्यान्वयन समकक्ष इस तरह से है जो वास्तव में आवश्यक arrayFilters से गुजरने के अनुकूल है बहस। इसलिए यदि आप एक विकास श्रृंखला या रिलीज कैंडिडेट सर्वर के साथ "खेल" रहे हैं, तो आपको वास्तव में "ब्लीडिंग एज" और अप्रकाशित ड्राइवरों के साथ भी काम करने के लिए तैयार रहना चाहिए।
लेकिन आप वास्तव में ऐसा कर सकते हैं जैसा कि किसी भी ड्राइवर में दिखाया गया है, सही रूप में जहां जारी किया जा रहा आदेश बदला नहीं जा रहा है।
<ब्लॉकक्वॉट>11 नवंबर 2017 को लिखे जाने तक कोई "आधिकारिक" . नहीं है MongoDB या समर्थित ड्राइवरों की रिहाई जो वास्तव में इसे लागू करते हैं। उत्पादन का उपयोग केवल सर्वर और समर्थित ड्राइवरों के आधिकारिक रिलीज पर आधारित होना चाहिए।