आप mapReduce का उपयोग करके ऐसा कर सकते हैं। :
रूट स्तर पर केवल फ़ील्ड नाम प्राप्त करने के लिए:
db.collection.mapReduce(function () {
Object.keys(this).map(function(key) {
if (key.match(/^fk/)) emit(key, null);
// OR: key.indexOf("fk") === 0
});
}, function(/* key, values */) {
// No need for params or to return anything in the
// reduce, just pass an empty function.
}, { out: { inline: 1 }});
यह कुछ इस तरह आउटपुट करेगा:
{
"results": [{
"_id": "fkKey1",
"value": null
}, {
"_id": "fkKey2",
"value": null
}, {
"_id": "fkKey3",
"value": null
}],
"timeMillis": W,
"counts": {
"input": X,
"emit": Y,
"reduce": Z,
"output": 3
},
"ok" : 1
}
फ़ील्ड नाम और कोई या सभी (संपूर्ण दस्तावेज़) इसके मान प्राप्त करने के लिए:
db.test.mapReduce(function () {
var obj = this;
Object.keys(this).map(function(key) {
// With `obj[key]` you will get the value of the field as well.
// You can change `obj[key]` for:
// - `obj` to return the whole document.
// - `obj._id` (or any other field) to return its value.
if (key.match(/^fk/)) emit(key, obj[key]);
});
}, function(key, values) {
// We can't return values or an array directly yet:
return { values: values };
}, { out: { inline: 1 }});
यह कुछ इस तरह आउटपुट करेगा:
{
"results": [{
"_id": "fkKey1",
"value": {
"values": [1, 4, 6]
}
}, {
"_id": "fkKey2",
"value": {
"values": ["foo", "bar"]
}
}],
"timeMillis": W,
"counts": {
"input": X,
"emit": Y,
"reduce": Z,
"output": 2
},
"ok" : 1
}
उपदस्तावेज़ों में फ़ील्ड नाम प्राप्त करने के लिए (बिना पथ):
ऐसा करने के लिए आपको store JavaScript functions on the Server
:
db.system.js.save({ _id: "hasChildren", value: function(obj) {
return typeof obj === "object";
}});
db.system.js.save({ _id: "getFields", value: function(doc) {
Object.keys(doc).map(function(key) {
if (key.match(/^fk/)) emit(key, null);
if (hasChildren(doc[key])) getFields(doc[key])
});
}});
और अपना नक्शा इसमें बदलें:
function () {
getFields(this);
}
अब db.loadServerScripts()
चलाएं उन्हें लोड करने के लिए।
उपदस्तावेजों में फ़ील्ड नाम प्राप्त करने के लिए (पथ के साथ):
पिछला संस्करण केवल फ़ील्ड नाम लौटाएगा, न कि उन्हें प्राप्त करने के लिए संपूर्ण पथ, जिसकी आपको आवश्यकता होगी यदि आप उन कुंजियों का नाम बदलना चाहते हैं। रास्ता पाने के लिए:
db.system.js.save({ _id: "getFields", value: function(doc, prefix) {
Object.keys(doc).map(function(key) {
if (key.match(/^fk/)) emit(prefix + key, null);
if (hasChildren(doc[key]))
getFields(doc[key], prefix + key + '.')
});
}});
और अपना नक्शा इसमें बदलें:
function () {
getFields(this, '');
}
अतिव्यापी पथ मिलान बहिष्कृत करने के लिए:
ध्यान दें कि यदि आपके पास fkfoo.fkbar
. फ़ील्ड है , यह वापस आ जाएगा fkfoo
और fkfoo.fkbar
. यदि आप ओवरलैपिंग पथ मिलान नहीं चाहते हैं, तो:
db.system.js.save({ _id: "getFields", value: function(doc, prefix) {
Object.keys(doc).map(function(key) {
if (hasChildren(doc[key]))
getFields(doc[key], prefix + key + '.')
else if (key.match(/^fk/)) emit(prefix + key, null);
});
}});
अपने प्रश्न पर वापस जा रहे हैं, उन क्षेत्रों का नाम बदलकर:
इस अंतिम विकल्प के साथ, आपको वे सभी पथ मिलते हैं जिनमें कुंजियाँ शामिल होती हैं जो fk
. से शुरू होती हैं , इसलिए आप $rename
का उपयोग कर सकते हैं
उसके लिए।
हालांकि, $rename
उन लोगों के लिए काम नहीं करता जिनमें सरणियाँ हैं, इसलिए उनके लिए आप का उपयोग कर सकते हैं। forEach
अद्यतन करने के लिए। देखें MongoDB सरणी के भीतर डेटाबेस फ़ील्ड का नाम बदलें
ए>
प्रदर्शन नोट:
MapReduce विशेष रूप से तेज़ विचार नहीं है, इसलिए आप { out: "fk_fields"}
निर्दिष्ट करना चाह सकते हैं परिणामों को fk_fields
. नामक एक नए संग्रह में आउटपुट करने के लिए और उन परिणामों को बाद में क्वेरी करें, लेकिन यह आपके उपयोग के मामले पर निर्भर करेगा।
विशिष्ट मामलों के लिए संभावित अनुकूलन (संगत स्कीमा):
साथ ही, ध्यान दें कि यदि आप जानते हैं कि आपके दस्तावेज़ों की स्कीमा हमेशा समान होती है, तो आपको इसके फ़ील्ड प्राप्त करने के लिए उनमें से किसी एक को जांचना होगा, ताकि आप limit: 1
जोड़कर ऐसा कर सकें। विकल्प ऑब्जेक्ट के लिए या findOne
और आवेदन स्तर में इसके क्षेत्रों को पढ़ना।