2012-07-23 18 views
7

मैं मोंगो का उपयोग करके कुछ सारांश आंकड़े उत्पन्न करने का एक तरीका ढूंढ रहा हूं। मान लीजिए मैं प्रपत्रमोंगो में बिनिंग और टैबलेट (अद्वितीय/गिनती)

{"name" : "Jeroen", "gender" : "m", "age" :27.53 } 

के कई रिकॉर्ड के साथ एक संग्रह है अब मैं लिंग और उम्र के लिए वितरण करना चाहते हैं। लिंग के लिए मान लें, केवल "m" और "f" मान हैं। मेरे संग्रह में पुरुषों और महिलाओं की कुल गिनती पाने का सबसे प्रभावी तरीका क्या है?

और उम्र के लिए, क्या कोई तरीका है जो कुछ 'कताई' करता है और मुझे सारांश की तरह हिस्टोग्राम देता है; यानी रिकॉर्ड की संख्या जहां आयु अंतराल में है: [0, 2), [2, 4), [4, 6) ... आदि?

उत्तर

2

कॉन्स्टेंटिन का जवाब सही था। MapReduce नौकरी हो जाता है। अगर दूसरों को यह दिलचस्प लगता है तो यहां पूर्ण समाधान दिया गया है।

लिंगों की गणना करने के लिए, मानचित्र फ़ंक्शन कुंजी प्रत्येक रिकॉर्ड के लिए this.gender विशेषता है। को कम समारोह तो बस उन्हें कहते हैं:

// count genders 
db.persons.mapReduce(
    function(){ 
     emit(this["gender"], {count: 1}) 
    }, function(key, values){ 
     var result = {count: 0}; 
     values.forEach(function(value) { 
      result.count += value.count; 
     }); 
     return result; 
    }, {out: { inline : 1}} 
); 

binning ऐसा करने के लिए, हम दो से निकटतम विभाजन करने के लिए नीचे दौर के लिए नक्शे समारोह में कुंजी सेट। इसलिए उदा। 10 और 11.9 999 के बीच कोई भी मूल्य एक ही कुंजी "10-12" प्राप्त करेगा। और उसके बाद फिर हम बस उन्हें जोड़:

db.responses.mapReduce(
    function(){ 
     var x = Math.floor(this["age"]/2)*2; 
     var key = x + "-" + (x+2); 
     emit(key, {count: 1}) 
    }, function(state, values){ 
     var result = {count: 0}; 
     values.forEach(function(value) { 
      result.count += value.count; 
     }); 
     return result; 
    }, {out: { inline : 1}} 
); 
+0

यह अच्छा है। MapReduce() फ़ंक्शन के लिए मुझे दस्तावेज़ कहां मिल सकता है? मैंने एक खोज की लेकिन मुझे आधिकारिक स्रोत नहीं मिला ... – jimijazz

0

डेटा की मात्रा के आधार पर पुरुषों और महिलाओं की मात्रा को खोजने का सबसे प्रभावी तरीका बेवकूफ क्वेरी या मानचित्र नौकरी कम कर सकता है। बिनिंग सबसे अच्छा नक्शा के माध्यम से किया जाता है को कम:

नक्शा चरण अपने प्रमुख एक बिन है, और मान 1 है, और कम करने के चरण में तुम सिर्फ मूल्यों

+0

क्या आप इसे कुछ उदाहरण कोड के साथ चित्रित कर सकते हैं? – Jeroen

+0

आप तेजी से थे - मैं छुट्टी पर हूं और बहुत अधिक ऑफ़लाइन –

1

की कुल संख्या प्राप्त करने के लिए एक आसान तरीका योग पुरुष db.x.find({"gender": "m"}).count()

यदि आप केवल एक प्रश्न में नर और मादा दोनों की गणना करना चाहते हैं, तो कोई आसान तरीका नहीं है। मानचित्र/कमी एक संभावना होगी। या शायद नया aggregation frameworkबिनिंग आवश्यकता

मोंगो एकत्रीकरण के लिए बहुत अच्छा नहीं है, लेकिन यह कई छोटे वृद्धिशील अपडेटों के लिए शानदार है। तो मोंगो के साथ इस समस्या को हल करने का सबसे अच्छा तरीका एक पृथक संग्रह में एकत्रीकरण डेटा एकत्र करना होगा।

इसलिए, यदि आप एक दस्तावेज़ इस तरह के साथ एक आँकड़े संग्रह रखें:

stats: [ 
    { 
    "male": 23, 
    "female": 17, 
    "ageDistribution": { 
     "0_2" : 3, 
     "2_4" : 5, 
     "4_6" : 7 
    } 
    } 
] 

... तो हर आप जोड़ सकते हैं या अन्य संग्रह से एक व्यक्ति को निकालने के लिए, आप संबंधित क्षेत्रों ऊपर या में उलटी गिनती आंकड़े संग्रह। आँकड़े को

db.stats.update({"$inc": {"male": 1, "ageDistribution.2_4": 1}}) 

प्रश्नों बिजली इस तरह से तेजी से हो जाएगा, और आप शायद ही आँकड़े ऊपर और नीचे की गिनती से किसी भी प्रदर्शन भूमि के ऊपर ध्यान देंगे।

19

मैं सिर्फ नए एकत्रीकरण ढांचे, कि MongoDB संस्करण 2.2 (2.2.0-RC0 जारी की गई है) में उपलब्ध हो जाएगा जो नक्शे की तुलना में अधिक प्रदर्शन करना चाहिए था बाहर करने की कोशिश की कम करें क्योंकि यह जावास्क्रिप्ट पर भरोसा नहीं करता है।

इनपुट डेटा: लिंग के लिए

{ "_id" : 1, "age" : 22.34, "gender" : "f" } 
{ "_id" : 2, "age" : 23.9, "gender" : "f" } 
{ "_id" : 3, "age" : 27.4, "gender" : "f" } 
{ "_id" : 4, "age" : 26.9, "gender" : "m" } 
{ "_id" : 5, "age" : 26, "gender" : "m" } 

एकत्रीकरण आदेश:

db.collection.aggregate(
    {$project: {gender:1}}, 
    {$group: { 
     _id: "$gender", 
     count: {$sum: 1} 
    }}) 

परिणाम:

{"result" : 
    [ 
    {"_id" : "m", "count" : 2}, 
    {"_id" : "f", "count" : 3} 
    ], 
    "ok" : 1 
} 

डिब्बे में उम्र पाने के लिए:

db.collection.aggregate(
    {$project: { 
     ageLowerBound: {$subtract:["$age", {$mod:["$age",2]}]}} 
    }, 
    {$group: { 
     _id:"$ageLowerBound", 
     count:{$sum:1} 
    } 
}) 

परिणाम:

{"result" : 
    [ 
     {"_id" : 26, "count" : 3}, 
     {"_id" : 22, "count" : 2} 
    ], 
    "ok" : 1 
} 
+0

मुझे समेकन ढांचे में दिलचस्पी रखने वाले किसी भी व्यक्ति के लिए भी ध्यान रखना चाहिए कि कुल कमांड में $ match का उपयोग करके जितना जल्दी हो सके पूर्ण टेबल स्कैन को रोकने के लिए अनुशंसा की जाती है। – Jenna

+2

मनमानी डिब्बे के लिए जो कुछ संख्या के गुणक नहीं हैं, आप [$ cond] (http://docs.mongodb.org/manual/reference/operator/aggregation/cond/#exp._S_cond) का उपयोग कर सकते हैं हालांकि वाक्यविन्यास है भयानक: $ प्रोजेक्ट: {आयुलोवरबाउंड: {$ cond: [{$ lt: [$ age, 2]}, "0", {$ cond: [{$ lt: [$ age, 4]}, "2", "4"]}]}} ... या ऐसा कुछ। –

+0

@ जेना हम GeoJSON प्रविष्टियों के खिलाफ क्या कर सकते हैं? – Pei

0

मोंगो 3.4 के साथ इस भी आसान हो गया है, नए $ बाल्टी और $bucketAuto एकत्रीकरण कार्यों के लिए धन्यवाद।

db.bucket.aggregate([ 
    { 
    $bucketAuto: { 
     groupBy: "$gender", 
     buckets: 2 
    } 
    } 
]) 
निम्नलिखित इनपुट डेटा के साथ

:

{ "_id" : 1, "age" : 22.34, "gender" : "f" } 
{ "_id" : 2, "age" : 23.9, "gender" : "f" } 
{ "_id" : 3, "age" : 27.4, "gender" : "f" } 
{ "_id" : 4, "age" : 26.9, "gender" : "m" } 
{ "_id" : 5, "age" : 26, "gender" : "m" } 

यह निम्न परिणाम देता है: दो समूहों में निम्न क्वेरी ऑटो बाल्टी

{ "_id" : { "min" : "f", "max" : "m" }, "count" : 3 } 
{ "_id" : { "min" : "m", "max" : "m" }, "count" : 2 } 

ध्यान दें, बाल्टी और ऑटो बाल्टी आमतौर पर निरंतर चर (संख्यात्मक, तिथि) के लिए उपयोग किया जाता है, लेकिन इस मामले में ऑटो-बाल्टी बस ठीक काम करता है।

0

@ColinE के जवाब हिस्टोग्राम के लिए binning के आधार पर द्वारा

db.persons.aggregate([ 
 { 
    $bucket: { 
    groupBy: "$j.age", 
    boundaries: [0,2,4,6,8,10,12,14,16,18,20], 
    default: "Other", 
    output: { 
     "count": { $sum: 1 } 
    } 
    } 
], 
{allowDiskUse:true}) 

$bucketAuto किया जा सकता है मेरे लिए काम नहीं किया, क्योंकि उस बाल्टी एक लघुगणकीय पैमाने पर एकत्र होने के लिए लग रहे हैं। allowDiskUse केवल तभी आवश्यक है यदि आपके पास लाखों दस्तावेज़

संबंधित मुद्दे