व्यक्तिगत रूप से मैं परिणामस्वरूप "डेटा" को चाबियों के नाम के रूप में बदलने का बड़ा प्रशंसक नहीं हूं। एकत्रीकरण ढांचे के सिद्धांत सहमत होते हैं क्योंकि इस प्रकार का संचालन भी समर्थित नहीं है।
इसलिए व्यक्तिगत प्राथमिकता "डेटा" को "डेटा" के रूप में बनाए रखना है और स्वीकार करना है कि संसाधित आउटपुट वास्तव में एक सुसंगत ऑब्जेक्ट डिज़ाइन के लिए बेहतर और अधिक तार्किक है:
db.people.aggregate([
{ "$group": {
"_id": "$sex",
"hobbies": { "$push": "$hobbies" },
"total": { "$sum": 1 }
}},
{ "$unwind": "$hobbies" },
{ "$unwind": "$hobbies" },
{ "$group": {
"_id": {
"sex": "$_id",
"hobby": "$hobbies"
},
"total": { "$first": "$total" },
"hobbyCount": { "$sum": 1 }
}},
{ "$group": {
"_id": "$_id.sex",
"total": { "$first": "$total" },
"hobbies": {
"$push": { "name": "$_id.hobby", "count": "$hobbyCount" }
}
}}
])
जो इस तरह का परिणाम देता है:
[
{
"_id" : "female",
"total" : 1,
"hobbies" : [
{
"name" : "tennis",
"count" : 1
},
{
"name" : "football",
"count" : 1
}
]
},
{
"_id" : "male",
"total" : 2,
"hobbies" : [
{
"name" : "swimming",
"count" : 1
},
{
"name" : "tennis",
"count" : 2
},
{
"name" : "football",
"count" : 2
}
]
}
]
तो आरंभिक $group
प्रति "सेक्स" की गिनती करता है और शौक को सरणियों की एक सरणी में ढेर कर देता है। फिर आपको सामान्य करने के लिए $unwind
एकवचन आइटम प्राप्त करने के लिए दो बार, $group
प्रत्येक सेक्स के तहत प्रति शौक का योग प्राप्त करने के लिए और अंत में अकेले प्रत्येक सेक्स के लिए एक सरणी को फिर से समूहित करें।
यह वही डेटा है, इसकी एक सुसंगत और जैविक संरचना है जिसे संसाधित करना आसान है, और MongoDB और एकत्रीकरण ढांचा इस आउटपुट के उत्पादन में काफी खुश था।
यदि आपको वास्तव में अपने डेटा को चाबियों के नाम में परिवर्तित करना है (और मैं अभी भी आपको अनुशंसा करता हूं कि यह डिजाइन में पालन करने के लिए एक अच्छा पैटर्न नहीं है), तो अंतिम स्थिति से ऐसा परिवर्तन करना क्लाइंट कोड प्रोसेसिंग के लिए काफी छोटा है। शेल के लिए उपयुक्त मूल जावास्क्रिप्ट उदाहरण के रूप में:
var out = db.people.aggregate([
{ "$group": {
"_id": "$sex",
"hobbies": { "$push": "$hobbies" },
"total": { "$sum": 1 }
}},
{ "$unwind": "$hobbies" },
{ "$unwind": "$hobbies" },
{ "$group": {
"_id": {
"sex": "$_id",
"hobby": "$hobbies"
},
"total": { "$first": "$total" },
"hobbyCount": { "$sum": 1 }
}},
{ "$group": {
"_id": "$_id.sex",
"total": { "$first": "$total" },
"hobbies": {
"$push": { "name": "$_id.hobby", "count": "$hobbyCount" }
}
}}
]).toArray();
out.forEach(function(doc) {
var obj = {};
doc.hobbies.sort(function(a,b) { return a.count < b.count });
doc.hobbies.forEach(function(hobby) {
obj[hobby.name] = hobby.count;
});
doc.hobbies = obj;
printjson(doc);
});
और फिर आप मूल रूप से प्रत्येक कर्सर परिणाम को वांछित आउटपुट फॉर्म में संसाधित कर रहे हैं, जो वास्तव में एक एकत्रीकरण फ़ंक्शन नहीं है जो वास्तव में सर्वर पर आवश्यक है:
{
"_id" : "female",
"total" : 1,
"hobbies" : {
"tennis" : 1,
"football" : 1
}
}
{
"_id" : "male",
"total" : 2,
"hobbies" : {
"tennis" : 2,
"football" : 2,
"swimming" : 1
}
}
जहां कर्सर के स्ट्रीम प्रोसेसिंग में उस तरह के हेरफेर को लागू करने के लिए यह भी काफी तुच्छ होना चाहिए, क्योंकि यह मूल रूप से एक ही तर्क है, क्योंकि यह मूल रूप से एक ही तर्क है।
दूसरी ओर, आप इसके बजाय हमेशा mapReduce का उपयोग करके सर्वर पर सभी हेरफेर को लागू कर सकते हैं:
db.people.mapReduce(
function() {
emit(
this.sex,
{
"total": 1,
"hobbies": this.hobbies.map(function(key) {
return { "name": key, "count": 1 };
})
}
);
},
function(key,values) {
var obj = {},
reduced = {
"total": 0,
"hobbies": []
};
values.forEach(function(value) {
reduced.total += value.total;
value.hobbies.forEach(function(hobby) {
if ( !obj.hasOwnProperty(hobby.name) )
obj[hobby.name] = 0;
obj[hobby.name] += hobby.count;
});
});
reduced.hobbies = Object.keys(obj).map(function(key) {
return { "name": key, "count": obj[key] };
}).sort(function(a,b) {
return a.count < b.count;
});
return reduced;
},
{
"out": { "inline": 1 },
"finalize": function(key,value) {
var obj = {};
value.hobbies.forEach(function(hobby) {
obj[hobby.name] = hobby.count;
});
value.hobbies = obj;
return value;
}
}
)
जहां mapReduce की अपनी अलग आउटपुट शैली है, लेकिन समान सिद्धांतों का उपयोग संचय और हेरफेर में किया जाता है, यदि संभव नहीं तो एकत्रीकरण ढांचा जितना कुशल हो सकता है:
"results" : [
{
"_id" : "female",
"value" : {
"total" : 1,
"hobbies" : {
"football" : 1,
"tennis" : 1
}
}
},
{
"_id" : "male",
"value" : {
"total" : 2,
"hobbies" : {
"football" : 2,
"tennis" : 2,
"swimming" : 1
}
}
}
]
दिन के अंत में, मैं अभी भी कहता हूं कि प्रसंस्करण का पहला रूप सबसे कुशल है और मेरे दिमाग को डेटा आउटपुट का सबसे स्वाभाविक और सुसंगत कार्य प्रदान करता है, यहां तक कि डेटा बिंदुओं को कुंजियों के नाम में बदलने का प्रयास किए बिना। उस पैटर्न का पालन करने पर विचार करना शायद सबसे अच्छा है, लेकिन अगर आपको वास्तव में जरूरी है, तो प्रसंस्करण के विभिन्न तरीकों में परिणामों को वांछित रूप में हेरफेर करने के तरीके हैं।