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

मैं नेस्टेड दस्तावेज़ों के लिए एकत्रीकरण पाइपलाइन में खोलना चरणों को कैसे कम कर सकता हूं?

जब तक आपके डेटा में प्रति दस्तावेज़ अद्वितीय सेंसर और टैग रीडिंग है, जो आज तक आपने प्रस्तुत किया है, तो आपको बस $अनविंड बिल्कुल।

वास्तव में, आपको वास्तव में केवल एक $group<की आवश्यकता है /कोड> :

db.endpoints.aggregate([
  // In reality you would $match to limit the selection of documents
  { "$match": { 
    "DateTime": { "$gte": new Date("2018-05-01"), "$lt": new Date("2018-06-01") }
  }},
  { "$group": {
    "_id": "$EndpointId",
    "FirstActivity" : { "$min" : "$DateTime" },
    "LastActivity" : { "$max" : "$DateTime" },
    "RequestCount": { "$sum": 1 },
    "TagCount": {
      "$sum": {
        "$size": { "$setUnion": ["$Tags.Uid",[]] }
      }
    },
    "SensorCount": {
      "$sum": {
        "$sum": {
          "$map": {
            "input": { "$setUnion": ["$Tags.Uid",[]] },
            "as": "tag",
            "in": {
              "$size": {
                "$reduce": {
                  "input": {
                    "$filter": {
                      "input": {
                        "$map": {
                          "input": "$Tags",
                          "in": {
                            "Uid": "$$this.Uid",
                            "Type": "$$this.Sensors.Type"
                          }
                        }
                      },
                      "cond": { "$eq": [ "$$this.Uid", "$$tag" ] }
                    }
                  },
                  "initialValue": [],
                  "in": { "$setUnion": [ "$$value", "$$this.Type" ] }
                }
              }
            }
          }
        }
      }
    }
  }}
])

या यदि आपको वास्तव में विभिन्न दस्तावेज़ों से "सेंसर" और "टैग" के उन "अद्वितीय" मूल्यों को संचित करने की आवश्यकता है, तो आपको अभी भी प्रारंभिक $अनविंड सही समूहन प्राप्त करने के लिए कथन, लेकिन जितना आपके पास वर्तमान में है उतना कहीं नहीं:

db.endpoints.aggregate([
  // In reality you would $match to limit the selection of documents
  { "$match": { 
    "DateTime": { "$gte": new Date("2018-05-01"), "$lt": new Date("2018-06-01") }
  }},
  { "$unwind": "$Tags" },
  { "$unwind": "$Tags.Sensors" },
  { "$group": {
    "_id": {
      "EndpointId": "$EndpointId",
      "Uid": "$Tags.Uid",
      "Type": "$Tags.Sensors.Type"
    },
    "FirstActivity": { "$min": "$DateTime" },
    "LastActivity": { "$max": "$DateTime" },
    "RequestCount": { "$addToSet": "$_id" }
  }},
  { "$group": {
    "_id": {
      "EndpointId": "$_id.EndpointId",
      "Uid": "$_id.Uid",
    },
    "FirstActivity": { "$min": "$FirstActivity" },
    "LastActivity": { "$max": "$LastActivity" },
    "count": { "$sum": 1 },
    "RequestCount": { "$addToSet": "$RequestCount" }
  }},
  { "$group": {
    "_id": "$_id.EndpointId",
    "FirstActivity": { "$min": "$FirstActivity" },
    "LastActivity": { "$max": "$LastActivity" },
    "TagCount": { "$sum": 1 },
    "SensorCount": { "$sum": "$count" },
    "RequestCount": { "$addToSet": "$RequestCount" }
  }},
  { "$addFields": {
    "RequestCount": {
      "$size": {
        "$reduce": {
          "input": {
            "$reduce": {
              "input": "$RequestCount",
              "initialValue": [],
              "in": { "$setUnion": [ "$$value", "$$this" ] }
            }
          },
          "initialValue": [],
          "in": { "$setUnion": [ "$$value", "$$this" ] }
        }
      }
    }
  }}
],{ "allowDiskUse": true })

और MongoDB 4.0 से आप उपयोग कर सकते हैं $toString ObjectId . पर _id . के अंदर और RequestCount . रखने के लिए बस उनके लिए अद्वितीय कुंजियों को मर्ज करें $mergeObjects का इस्तेमाल करके . यह नेस्टेड सरणी सामग्री को आगे बढ़ाने और इसे समतल करने की तुलना में क्लीनर और थोड़ा अधिक स्केलेबल है

db.endpoints.aggregate([
  // In reality you would $match to limit the selection of documents
  { "$match": { 
    "DateTime": { "$gte": new Date("2018-05-01"), "$lt": new Date("2018-06-01") }
  }},
  { "$unwind": "$Tags" },
  { "$unwind": "$Tags.Sensors" },
  { "$group": {
    "_id": {
      "EndpointId": "$EndpointId",
      "Uid": "$Tags.Uid",
      "Type": "$Tags.Sensors.Type"
    },
    "FirstActivity": { "$min": "$DateTime" },
    "LastActivity": { "$max": "$DateTime" },
    "RequestCount": {
      "$mergeObjects": {
        "$arrayToObject": [[{ "k": { "$toString": "$_id" }, "v": 1 }]]
      }
    }
  }},
  { "$group": {
    "_id": {
      "EndpointId": "$_id.EndpointId",
      "Uid": "$_id.Uid",
    },
    "FirstActivity": { "$min": "$FirstActivity" },
    "LastActivity": { "$max": "$LastActivity" },
    "count": { "$sum": 1 },
    "RequestCount": { "$mergeObjects": "$RequestCount" }
  }},
  { "$group": {
    "_id": "$_id.EndpointId",
    "FirstActivity": { "$min": "$FirstActivity" },
    "LastActivity": { "$max": "$LastActivity" },
    "TagCount": { "$sum": 1 },
    "SensorCount": { "$sum": "$count" },
    "RequestCount": { "$mergeObjects": "$RequestCount" }
  }},
  { "$addFields": {
    "RequestCount": {
      "$size": {
        "$objectToArray": "$RequestCount"
      }
    }
  }}
],{ "allowDiskUse": true })

दोनों में से कोई भी प्रपत्र समान डेटा लौटाता है, हालांकि परिणाम में कुंजियों का क्रम भिन्न हो सकता है:

{
        "_id" : "89799bcc-e86f-4c8a-b340-8b5ed53caf83",
        "FirstActivity" : ISODate("2018-05-06T19:05:02.666Z"),
        "LastActivity" : ISODate("2018-05-06T19:05:02.666Z"),
        "RequestCount" : 2,
        "TagCount" : 4,
        "SensorCount" : 16
}

परिणाम इन नमूना दस्तावेजों से प्राप्त होता है जो आपने मूल रूप से विषय पर मूल प्रश्न में एक नमूना स्रोत के रूप में दिया था। :

{
    "_id" : ObjectId("5aef51dfaf42ea1b70d0c4db"),    
    "EndpointId" : "89799bcc-e86f-4c8a-b340-8b5ed53caf83",    
    "DateTime" : ISODate("2018-05-06T19:05:02.666Z"),
    "Url" : "test",
    "Tags" : [ 
        {
            "Uid" : "C1:3D:CA:D4:45:11",
            "Type" : 1,
            "DateTime" : ISODate("2018-05-06T19:05:02.666Z"),
            "Sensors" : [ 
                {
                    "Type" : 1,
                    "Value" : NumberDecimal("-95")
                }, 
                {
                    "Type" : 2,
                    "Value" : NumberDecimal("-59")
                }, 
                {
                    "Type" : 3,
                    "Value" : NumberDecimal("11.029802536740132")
                }, 
                {
                    "Type" : 4,
                    "Value" : NumberDecimal("27.25")
                }, 
                {
                    "Type" : 6,
                    "Value" : NumberDecimal("2924")
                }
            ]
        },         
        {
            "Uid" : "C1:3D:CA:D4:45:11",
            "Type" : 1,
            "DateTime" : ISODate("2018-05-06T19:05:02.666Z"),
            "Sensors" : [ 
                {
                    "Type" : 1,
                    "Value" : NumberDecimal("-95")
                }, 
                {
                    "Type" : 2,
                    "Value" : NumberDecimal("-59")
                }, 
                {
                    "Type" : 3,
                    "Value" : NumberDecimal("11.413037961112279")
                }, 
                {
                    "Type" : 4,
                    "Value" : NumberDecimal("27.25")
                }, 
                {
                    "Type" : 6,
                    "Value" : NumberDecimal("2924")
                }
            ]
        },          
        {
            "Uid" : "E5:FA:2A:35:AF:DD",
            "Type" : 1,
            "DateTime" : ISODate("2018-05-06T19:05:02.666Z"),
            "Sensors" : [ 
                {
                    "Type" : 1,
                    "Value" : NumberDecimal("-97")
                }, 
                {
                    "Type" : 2,
                    "Value" : NumberDecimal("-58")
                }, 
                {
                    "Type" : 3,
                    "Value" : NumberDecimal("10.171658037099185")
                }
            ]
        }
    ]
}

/* 2 */
{
    "_id" : ObjectId("5aef51e0af42ea1b70d0c4dc"),    
    "EndpointId" : "89799bcc-e86f-4c8a-b340-8b5ed53caf83",    
    "Url" : "test",
    "Tags" : [ 
        {
            "Uid" : "E2:02:00:18:DA:40",
            "Type" : 1,
            "DateTime" : ISODate("2018-05-06T19:05:04.574Z"),
            "Sensors" : [ 
                {
                    "Type" : 1,
                    "Value" : NumberDecimal("-98")
                }, 
                {
                    "Type" : 2,
                    "Value" : NumberDecimal("-65")
                }, 
                {
                    "Type" : 3,
                    "Value" : NumberDecimal("7.845424441900629")
                }, 
                {
                    "Type" : 4,
                    "Value" : NumberDecimal("0.0")
                }, 
                {
                    "Type" : 6,
                    "Value" : NumberDecimal("3012")
                }
            ]
        }, 
        {
            "Uid" : "12:3B:6A:1A:B7:F9",
            "Type" : 1,
            "DateTime" : ISODate("2018-05-06T19:05:04.574Z"),
            "Sensors" : [ 
                {
                    "Type" : 1,
                    "Value" : NumberDecimal("-95")
                }, 
                {
                    "Type" : 2,
                    "Value" : NumberDecimal("-59")
                }, 
                {
                    "Type" : 3,
                    "Value" : NumberDecimal("12.939770381907275")
                }
            ]
        }
    ]
}

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

अब तक दिया गया आपका नमूना डेटा केवल यह दर्शाता है कि ये मान "प्रत्येक दस्तावेज़ के भीतर अद्वितीय" हैं, इसलिए पहला दिया गया फॉर्म सबसे इष्टतम होगा यदि यह सभी शेष डेटा के मामले में है।

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

अनुकूलन पर बिंदु का अर्थ है कि आपको केवल "दो बार" ऐसा करने की आवश्यकता है क्योंकि केवल दो सरणियाँ हैं। एक के बाद एक करना $group से $unwind से $group हमेशा एक निश्चित संकेत है कि आप वास्तव में कुछ गलत कर रहे हैं। एक बार जब आप "कुछ अलग कर लेते हैं" तो आपको केवल "उसे वापस एक साथ रखना" चाहिए एक बार . जैसा कि यहां दिखाया गया है, श्रेणीबद्ध चरणों की एक श्रृंखला में एक बार . है दृष्टिकोण जो अनुकूलित करता है।

आपके प्रश्न के दायरे से बाहर अभी भी बना हुआ है:

  • प्रसंस्कृत दस्तावेज़ों को कम करने के लिए क्वेरी में अन्य यथार्थवादी बाधाएं जोड़ें, शायद "बैच" में भी ऐसा करें और परिणामों को संयोजित करें
  • डिस्क उपयोग की अनुमति दें जोड़ें अस्थायी भंडारण का उपयोग करने के लिए पाइपलाइन का विकल्प। (वास्तव में आदेशों पर प्रदर्शित)
  • विचार करें कि "नेस्टेड सरणियाँ" संभवतः उस विश्लेषण के लिए सर्वोत्तम संग्रहण विधि नहीं हैं जो आप करना चाहते हैं। यह हमेशा अधिक कुशल होता है जब आप जानते हैं कि आपको $unwind<की आवश्यकता है /कोड> डेटा को उस "अनवाउंड" रूप में सीधे एक संग्रह में लिखने के लिए।


  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. FindOne काम करता है लेकिन सभी नहीं मिलता/ढूंढें

  2. एक नेवला दस्तावेज़ के अंदर एक सरणी को क्वेरी करना

  3. उल्का.जेएस में एक Mongo.db संग्रह को कैसे अपडेट करें?

  4. BadValue अमान्य है या कोई उपयोगकर्ता स्थान सेट नहीं है। कृपया सुनिश्चित करें कि LANG और/या LC_* पर्यावरण चर सही ढंग से सेट हैं

  5. यह देखने का सबसे तेज़ तरीका क्या है कि MongoDB का अंतिम अपडेट कब किया गया था

© कॉपीराइट http://hi.sqldat.com सर्वाधिकार सुरक्षित