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

नेस्टेड सरणियों का MongoDB प्रोजेक्शन

2017 अपडेट

इस तरह के एक अच्छी तरह से रखा गया प्रश्न आधुनिक प्रतिक्रिया का पात्र है। अनुरोधित सरणी फ़िल्टरिंग वास्तव में आधुनिक मोंगोडीबी रिलीज 3.2 में केवल $match के माध्यम से किया जा सकता है और $project पाइपलाइन चरण, मूल सादे क्वेरी ऑपरेशन की तरह।

db.accounts.aggregate([
  { "$match": {
    "email" : "[email protected]",
    "groups": {
      "$elemMatch": { 
        "name": "group1",
        "contacts.localId": { "$in": [ "c1","c3", null ] }
      }
    }
  }},
  { "$addFields": {
    "groups": {
      "$filter": {
        "input": {
          "$map": {
            "input": "$groups",
            "as": "g",
            "in": {
              "name": "$$g.name",
              "contacts": {
                "$filter": {
                  "input": "$$g.contacts",
                  "as": "c",
                  "cond": {
                    "$or": [
                      { "$eq": [ "$$c.localId", "c1" ] },
                      { "$eq": [ "$$c.localId", "c3" ] }
                    ]
                  } 
                }
              }
            }
          }
        },
        "as": "g",
        "cond": {
          "$and": [
            { "$eq": [ "$$g.name", "group1" ] },
            { "$gt": [ { "$size": "$$g.contacts" }, 0 ] }
          ]
        }
      }
    }
  }}
])

यह $filter . का उपयोग करता है और $map ऑपरेटरों को केवल शर्तों को पूरा करने के लिए सरणियों से तत्वों को वापस करने के लिए, और प्रदर्शन के लिए $unwind का उपयोग करने से कहीं बेहतर है . चूंकि पाइपलाइन चरण प्रभावी रूप से एक .find() से "क्वेरी" और "प्रोजेक्ट" की संरचना को प्रतिबिंबित करते हैं। संचालन, यहां प्रदर्शन मूल रूप से इस तरह और संचालन के बराबर है।

ध्यान दें कि जहां इरादा वास्तव में काम करना है "सभी दस्तावेज़ों में" "एक" के बजाय "एकाधिक" दस्तावेज़ों में से विवरण एक साथ लाने के लिए, इसके लिए आमतौर पर कुछ प्रकार के $unwind की आवश्यकता होगी ऐसा करने के लिए ऑपरेशन, जैसे कि "ग्रुपिंग" के लिए ऐरे आइटम्स को एक्सेस करने योग्य बनाना।

यह मूल रूप से दृष्टिकोण है:

db.accounts.aggregate([
    // Match the documents by query
    { "$match": {
        "email" : "[email protected]",
        "groups.name": "group1",
        "groups.contacts.localId": { "$in": [ "c1","c3", null ] },
    }},

    // De-normalize nested array
    { "$unwind": "$groups" },
    { "$unwind": "$groups.contacts" },

    // Filter the actual array elements as desired
    { "$match": {
        "groups.name": "group1",
        "groups.contacts.localId": { "$in": [ "c1","c3", null ] },
    }},

    // Group the intermediate result.
    { "$group": {
        "_id": { "email": "$email", "name": "$groups.name" },
        "contacts": { "$push": "$groups.contacts" }
    }},

    // Group the final result
    { "$group": {
        "_id": "$_id.email",
        "groups": { "$push": {
            "name": "$_id.name",
            "contacts": "$contacts" 
        }}
    }}
])

यह एक से अधिक मिलान पर "सरणी फ़िल्टरिंग" है जो .find() की मूल प्रक्षेपण क्षमताएं हैं नहीं कर सकता।

आपके पास "नेस्टेड" सरणियाँ हैं इसलिए आपको $unwind process को संसाधित करने की आवश्यकता है दो बार। अन्य कार्यों के साथ।



  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. MongoDB $toLower

  2. क्लाउड में ओपन सोर्स डेटाबेस का स्वचालन और प्रबंधन - ClusterControl की घोषणा 1.6

  3. ऑब्जेक्ट आईडी के लिए नेवला स्ट्रिंग

  4. MongoDB से पांडस डेटा फ्रेम में नेस्टेड डेटा प्राप्त करना

  5. $lookup . के बाद एकत्रीकरण फ़िल्टर