MongoDB
 sql >> डेटाबेस >  >> NoSQL >> MongoDB

एकत्रीकरण ढांचे का उपयोग करके समूह और गणना

ऐसा लगता है कि आपने इस पर शुरुआत कर दी है लेकिन आप कुछ अन्य अवधारणाओं में खो गए हैं। दस्तावेज़ों में सरणियों के साथ काम करते समय कुछ बुनियादी सच्चाईयाँ होती हैं, लेकिन चलिए वहीं से शुरू करते हैं जहाँ आपने छोड़ा था:

db.sample.aggregate([
    { "$group": {
        "_id": "$status",
        "count": { "$sum": 1 }
    }}
])

तो वह बस $group का उपयोग करने जा रहा है "स्थिति" फ़ील्ड के विभिन्न मूल्यों पर अपने दस्तावेज़ों को इकट्ठा करने के लिए पाइपलाइन और फिर "गिनती" के लिए एक और फ़ील्ड भी तैयार करें जो निश्चित रूप से 1 $sum पर प्रत्येक दस्तावेज़ के लिए ऑपरेटर मिला। यह आपको उस बिंदु पर रखता है जैसा आप वर्णन करते हैं:

{ "_id" : "done", "count" : 2 }
{ "_id" : "canceled", "count" : 1 }

यह इसका पहला चरण है और समझने में काफी आसान है, लेकिन अब आपको यह जानना होगा कि किसी सरणी से मान कैसे प्राप्त करें। "dot notation" ऐसा कुछ करने के लिए ठीक से अवधारणा:

db.sample.aggregate([
    { "$group": {
        "_id": "$status",
        "count": { "$sum": 1 },
        "total": { "$sum": "$devices.cost" }
    }}
])

लेकिन आप पाएंगे कि "कुल" वास्तव में 0 . होगा उनमें से प्रत्येक परिणाम के लिए:

{ "_id" : "done", "count" : 2, "total" : 0 }
{ "_id" : "canceled", "count" : 1, "total" : 0 }

क्यों? वैसे MongoDB एकत्रीकरण संचालन इस तरह समूहीकरण करते समय वास्तव में सरणी तत्वों को पार नहीं करता है। ऐसा करने के लिए, एग्रीगेशन फ्रेमवर्क में एक अवधारणा है जिसे कहा जाता है। $अनविंड . नाम अपेक्षाकृत आत्म-व्याख्यात्मक है। MongoDB में एक एम्बेडेड सरणी लिंक किए गए डेटा स्रोतों के बीच "एक-से-कई" एसोसिएशन होने की तरह है। तो क्या $unwind करता है ठीक उसी तरह का "जॉइन" परिणाम, जहां परिणामी "दस्तावेज़" सरणी की सामग्री और प्रत्येक माता-पिता के लिए डुप्लिकेट जानकारी पर आधारित होते हैं।

तो सरणी तत्वों पर कार्य करने के लिए आपको <का उपयोग करने की आवश्यकता है कोड>$अनविंड पहला। यह तार्किक रूप से आपको इस तरह कोड की ओर ले जाएगा:

db.sample.aggregate([
    { "$unwind": "$devices" },
    { "$group": {
        "_id": "$status",
        "count": { "$sum": 1 },
        "total": { "$sum": "$devices.cost" }
    }}
])

और फिर परिणाम:

{ "_id" : "done", "count" : 4, "total" : 700 }
{ "_id" : "canceled", "count" : 2, "total" : 350 }

लेकिन यह बिल्कुल सही नहीं है? याद रखें कि आपने अभी-अभी $अनविंड से क्या सीखा है और यह मूल जानकारी के साथ एक डी-सामान्यीकृत कैसे जुड़ता है? तो अब यह प्रत्येक दस्तावेज़ के लिए डुप्लिकेट किया गया है क्योंकि दोनों में दो सरणी सदस्य थे। इसलिए जबकि "कुल" फ़ील्ड सही है, "गिनती" प्रत्येक मामले में जितनी होनी चाहिए उससे दोगुनी है।

थोड़ी अधिक देखभाल करने की आवश्यकता है, इसलिए इसे एक ही $समूह चरण, यह दो में किया जाता है:

db.sample.aggregate([
    { "$unwind": "$devices" },
    { "$group": {
        "_id": "$_id",
        "status": { "$first": "$status" },
        "total": { "$sum": "$devices.cost" }
    }},
    { "$group": {
        "_id": "$status",
        "count": { "$sum": 1 },
        "total": { "$sum": "$total" }
    }}
])

जो अब सही योग के साथ परिणाम प्राप्त करता है:

{ "_id" : "canceled", "count" : 1, "total" : 350 }
{ "_id" : "done", "count" : 2, "total" : 700 }

अब संख्या सही है, लेकिन यह अभी भी ठीक वैसा नहीं है जैसा आप पूछ रहे हैं। मुझे लगता है कि आपको वहां रुकना चाहिए क्योंकि आप जिस तरह के परिणाम की उम्मीद कर रहे हैं वह वास्तव में अकेले एकत्रीकरण से केवल एक परिणाम के अनुकूल नहीं है। आप परिणाम के "अंदर" होने के लिए कुल की तलाश कर रहे हैं। यह वास्तव में वहां नहीं है, लेकिन छोटे डेटा पर यह ठीक है:

db.sample.aggregate([
    { "$unwind": "$devices" },
    { "$group": {
        "_id": "$_id",
        "status": { "$first": "$status" },
        "total": { "$sum": "$devices.cost" }
    }},
    { "$group": {
        "_id": "$status",
        "count": { "$sum": 1 },
        "total": { "$sum": "$total" }
    }},
    { "$group": {
        "_id": null,
        "data": { "$push": { "count": "$count", "total": "$total" } },
        "totalCost": { "$sum": "$total" }
    }}
])

और एक अंतिम परिणाम प्रपत्र:

{
    "_id" : null,
    "data" : [
            {
                    "count" : 1,
                    "total" : 350
            },
            {
                    "count" : 2,
                    "total" : 700
            }
    ],
    "totalCost" : 1050
}

लेकिन, "ऐसा मत करो" . MongoDB में 16MB की प्रतिक्रिया पर दस्तावेज़ सीमा है, जो कि BSON युक्ति की एक सीमा है। छोटे परिणामों पर आप इस तरह की सुविधा रैपिंग कर सकते हैं, लेकिन चीजों की बड़ी योजना में आप पहले के रूप में परिणाम चाहते हैं और या तो एक अलग क्वेरी या सभी दस्तावेजों से कुल प्राप्त करने के लिए पूरे परिणामों को पुनरावृत्त करने के साथ रहते हैं।

ऐसा प्रतीत होता है कि आप 2.6 से कम मोंगोडीबी संस्करण का उपयोग कर रहे हैं, या रोबोमोंगो शेल से आउटपुट की प्रतिलिपि बना रहे हैं जो नवीनतम संस्करण सुविधाओं का समर्थन नहीं करता है। मोंगोडीबी 2.6 से हालांकि एकत्रीकरण के परिणाम एकल बीएसओएन सरणी के बजाय "कर्सर" हो सकते हैं। तो समग्र प्रतिक्रिया 16MB से बहुत बड़ी हो सकती है, लेकिन केवल तब जब आप अंतिम उदाहरण के लिए दिखाए गए परिणामों के रूप में किसी एक दस्तावेज़ को संकुचित नहीं कर रहे हों।

यह उन मामलों में विशेष रूप से सच होगा जहां आप परिणामों को "पेजिंग" कर रहे थे, 100 से 1000 की परिणाम लाइनों के साथ, लेकिन आप एपीआई प्रतिक्रिया में वापस जाने के लिए "कुल" चाहते थे जब आप केवल 25 परिणामों का "पृष्ठ" वापस कर रहे हों एक समय।

किसी भी तरह, इससे आपको अपने सामान्य दस्तावेज़ फ़ॉर्म से अपेक्षित परिणामों के प्रकार प्राप्त करने के बारे में एक उचित मार्गदर्शिका मिलनी चाहिए। याद रखें $unwind सरणियों को संसाधित करने के लिए, और आम तौर पर $group अपने दस्तावेज़ और संग्रह समूहों से विभिन्न समूह स्तरों पर योग प्राप्त करने के लिए कई बार।




  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. MongoDB में जॉब शेड्यूलिंग

  2. अरबों रिकॉर्डों को एकत्रित करते समय बहुत अधिक खुली हुई फ़ाइलों की त्रुटि को कैसे ठीक करें

  3. mongodb में आंतरिक रूप से मेल खाने वाले फ़ील्ड

  4. MongoDB:$ या एक पूर्ण-पाठ खोज और एक $in

  5. मोंगोडीबी एसक्यूएल इंजेक्शन गड़बड़ी से कैसे बचता है?