MongoDB: एक में कई संग्रहों में से डेटा को कैसे मिलाएं?


229

मैं (MongoDB में) एक संग्रह में कई संग्रहों के डेटा को कैसे संयोजित कर सकता हूं?

क्या मैं मैप-कम का उपयोग कर सकता हूं और यदि हां तो कैसे?

मैं कुछ उदाहरणों की बहुत सराहना करूंगा क्योंकि मैं नौसिखिया हूं।


18
क्या आप केवल एक ही संग्रह में विभिन्न संग्रहों से डॉक्स कॉपी करना चाहते हैं या आपकी क्या योजना है? क्या आप "संयोजन" निर्दिष्ट कर सकते हैं? यदि आप केवल मोंगू शेल के माध्यम से कॉपी करना चाहते हैं db.collection1.find().forEach(function(doc){db.collection2.save(doc)});तो पर्याप्त है। कृपया अपने उपयोग किए गए ड्राइवर (जावा, php, ...) को निर्दिष्ट करें यदि आप मोंगो शेल का उपयोग नहीं करते हैं।
प्रोमेमसस

इसलिए मेरे पास अन्य संग्रह की तुलना में एक संग्रह (उपयोगकर्ताओं का कहना है) पता पुस्तिका संग्रह, पुस्तकों के संग्रह की सूची आदि का कहना है कि मैं कैसे कह सकता हूं कि user_id कुंजी इन संग्रह को केवल एक एकल संग्रह में जोड़ती है। ?
user697697

जवाबों:


147

यद्यपि आप यह वास्तविक समय नहीं कर सकते हैं, आप MongoDB 1.8+ मैप / कम / " http://www.mongodb.org/ " में "कम" आउट विकल्प का उपयोग करके डेटा को एक साथ मर्ज करने के लिए कई बार मानचित्र-कम चला सकते हैं । प्रदर्शन / DOCS / MapReduce # MapReduce-Outputoptions )। आपको दोनों संग्रहों में कुछ कुंजी रखने की आवश्यकता है जिसे आप एक _id के रूप में उपयोग कर सकते हैं।

उदाहरण के लिए, मान लीजिए कि आपके पास एक usersसंग्रह और एक हैcomments संग्रह है और आप एक नया संग्रह चाहते हैं जिसमें प्रत्येक टिप्पणी के लिए कुछ उपयोगकर्ता जनसांख्यिकीय जानकारी हो।

मान लीजिए कि usersसंग्रह में निम्नलिखित क्षेत्र हैं:

  • _ id
  • पहला नाम
  • अंतिम नाम
  • देश
  • लिंग
  • आयु

और फिर commentsसंग्रह में निम्नलिखित क्षेत्र हैं:

  • _ id
  • यूज़र आईडी
  • टिप्पणी
  • बनाया था

आप इस नक्शे को कम / कम करेंगे:

var mapUsers, mapComments, reduce;
db.users_comments.remove();

// setup sample data - wouldn't actually use this in production
db.users.remove();
db.comments.remove();
db.users.save({firstName:"Rich",lastName:"S",gender:"M",country:"CA",age:"18"});
db.users.save({firstName:"Rob",lastName:"M",gender:"M",country:"US",age:"25"});
db.users.save({firstName:"Sarah",lastName:"T",gender:"F",country:"US",age:"13"});
var users = db.users.find();
db.comments.save({userId: users[0]._id, "comment": "Hey, what's up?", created: new ISODate()});
db.comments.save({userId: users[1]._id, "comment": "Not much", created: new ISODate()});
db.comments.save({userId: users[0]._id, "comment": "Cool", created: new ISODate()});
// end sample data setup

mapUsers = function() {
    var values = {
        country: this.country,
        gender: this.gender,
        age: this.age
    };
    emit(this._id, values);
};
mapComments = function() {
    var values = {
        commentId: this._id,
        comment: this.comment,
        created: this.created
    };
    emit(this.userId, values);
};
reduce = function(k, values) {
    var result = {}, commentFields = {
        "commentId": '', 
        "comment": '',
        "created": ''
    };
    values.forEach(function(value) {
        var field;
        if ("comment" in value) {
            if (!("comments" in result)) {
                result.comments = [];
            }
            result.comments.push(value);
        } else if ("comments" in value) {
            if (!("comments" in result)) {
                result.comments = [];
            }
            result.comments.push.apply(result.comments, value.comments);
        }
        for (field in value) {
            if (value.hasOwnProperty(field) && !(field in commentFields)) {
                result[field] = value[field];
            }
        }
    });
    return result;
};
db.users.mapReduce(mapUsers, reduce, {"out": {"reduce": "users_comments"}});
db.comments.mapReduce(mapComments, reduce, {"out": {"reduce": "users_comments"}});
db.users_comments.find().pretty(); // see the resulting collection

इस बिंदु पर, आपके पास एक नया संग्रह होगा जिसे users_commentsमर्ज किया गया डेटा शामिल है और अब आप इसका उपयोग कर सकते हैं। इन कम किए गए संग्रहों में वे सभी हैं _idजो आपके नक्शे कार्यों में महत्वपूर्ण थे और फिर सभी मूल्य अंदर की एक उप-वस्तु हैंvalue कुंजी के - मान इन कम किए गए दस्तावेज़ों के शीर्ष स्तर पर नहीं हैं।

यह कुछ सरल उदाहरण है। आप इसे अधिक संग्रह के साथ दोहरा सकते हैं जितना आप कम संग्रह का निर्माण करना चाहते हैं। आप प्रक्रिया में डेटा का सारांश और एकत्रीकरण भी कर सकते हैं। संभवतः आप एक से अधिक कम करने वाले फ़ंक्शन को परिभाषित करेंगे क्योंकि मौजूदा फ़ील्ड्स को एकत्र करने और संरक्षित करने के लिए तर्क अधिक जटिल हो जाता है।

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

reduce = function(k, values) {
    var result = {};
    values.forEach(function(value) {
        var field;
        for (field in value) {
            if (value.hasOwnProperty(field)) {
                result[field] = value[field];
            }
        }
    });
    return result;
};

यदि आप users_commentsसंग्रह को समतल करना चाहते हैं तो यह प्रति टिप्पणी एक दस्तावेज़ है, इसके अतिरिक्त इसे चलाएं:

var map, reduce;
map = function() {
    var debug = function(value) {
        var field;
        for (field in value) {
            print(field + ": " + value[field]);
        }
    };
    debug(this);
    var that = this;
    if ("comments" in this.value) {
        this.value.comments.forEach(function(value) {
            emit(value.commentId, {
                userId: that._id,
                country: that.value.country,
                age: that.value.age,
                comment: value.comment,
                created: value.created,
            });
        });
    }
};
reduce = function(k, values) {
    var result = {};
    values.forEach(function(value) {
        var field;
        for (field in value) {
            if (value.hasOwnProperty(field)) {
                result[field] = value[field];
            }
        }
    });
    return result;
};
db.users_comments.mapReduce(map, reduce, {"out": "comments_with_demographics"});

इस तकनीक को निश्चित रूप से मक्खी पर नहीं किया जाना चाहिए। यह क्रोन जॉब के लिए अनुकूल है या ऐसा कुछ है जो समय-समय पर मर्ज किए गए डेटा को अपडेट करता है। संभवतः आप ensureIndexनए संग्रह पर चलना चाहते हैं, ताकि आप यह सुनिश्चित कर सकें कि आप इसके विरुद्ध शीघ्रता से प्रदर्शन कर सकते हैं (ध्यान रखें कि आपका डेटा अभी भी एक valueकुंजी के अंदर है , इसलिए यदि आप comments_with_demographicsटिप्पणी createdसमय पर अनुक्रमित करना चाहते हैं, तो यह होगाdb.comments_with_demographics.ensureIndex({"value.created": 1});


1
मैं शायद उत्पादन सॉफ्टवेयर में ऐसा कभी नहीं करूंगा, लेकिन यह अभी भी एक दुष्ट तकनीक है।
डेव ग्रिफ़िथ

3
धन्यवाद, डेव। मैंने बिना किसी समस्या के पिछले 3 महीनों के लिए उत्पादन में उच्च यातायात साइट के लिए निर्यात और रिपोर्टिंग तालिकाओं के निर्माण के लिए इस तकनीक का उपयोग किया। यहाँ एक और लेख है जो तकनीक के समान उपयोग का वर्णन करता है: tebros.com/2011/07/…
rmarscher

1
धन्यवाद @rmarscher आपके अतिरिक्त विवरण ने वास्तव में मुझे सब कुछ बेहतर समझने में मदद की।
बेन

5
मुझे एकत्रीकरण पाइपलाइन और नए $ लुकअप ऑपरेशन का उपयोग करके एक उदाहरण के साथ इस उत्तर को अपडेट करना चाहिए। जब तक मैं एक साथ एक उचित लेखन-अप नहीं डाल सकता, तब तक इसका उल्लेख करना। docs.mongodb.org/manual/reference/operator/aggregation/lookup
rmarscher

1
FYI करें जल्दी से grok को यह क्या करता है चाहने वालों के लिए, यहाँ क्या में है users_commentsकोड के पहले खंड के बाद संग्रह gist.github.com/nolanamy/83d7fb6a9bf92482a1c4311ad9c78835
नोलन एमी

127

MongoDB 3.2 अब एक को कई लुकअप से $ लुकिंग एग्रीगेशन चरण के माध्यम से एक में डेटा को संयोजित करने की अनुमति देता है । एक व्यावहारिक उदाहरण के रूप में, यह बताता है कि आपके पास दो अलग-अलग संग्रहों में विभाजित पुस्तकों के बारे में डेटा है।

booksनिम्नलिखित डेटा वाले पहले संग्रह को कहा जाता है :

{
    "isbn": "978-3-16-148410-0",
    "title": "Some cool book",
    "author": "John Doe"
}
{
    "isbn": "978-3-16-148999-9",
    "title": "Another awesome book",
    "author": "Jane Roe"
}

और दूसरा संग्रह, जिसे books_selling_dataनिम्नलिखित डेटा कहा जाता है :

{
    "_id": ObjectId("56e31bcf76cdf52e541d9d26"),
    "isbn": "978-3-16-148410-0",
    "copies_sold": 12500
}
{
    "_id": ObjectId("56e31ce076cdf52e541d9d28"),
    "isbn": "978-3-16-148999-9",
    "copies_sold": 720050
}
{
    "_id": ObjectId("56e31ce076cdf52e541d9d29"),
    "isbn": "978-3-16-148999-9",
    "copies_sold": 1000
}

दोनों संग्रहों को मर्ज करने के लिए निम्नलिखित तरीके से $ लुकअप का उपयोग करने की बात है:

db.books.aggregate([{
    $lookup: {
            from: "books_selling_data",
            localField: "isbn",
            foreignField: "isbn",
            as: "copies_sold"
        }
}])

इस एकत्रीकरण के बाद, booksसंग्रह निम्नलिखित की तरह दिखेगा:

{
    "isbn": "978-3-16-148410-0",
    "title": "Some cool book",
    "author": "John Doe",
    "copies_sold": [
        {
            "_id": ObjectId("56e31bcf76cdf52e541d9d26"),
            "isbn": "978-3-16-148410-0",
            "copies_sold": 12500
        }
    ]
}
{
    "isbn": "978-3-16-148999-9",
    "title": "Another awesome book",
    "author": "Jane Roe",
    "copies_sold": [
        {
            "_id": ObjectId("56e31ce076cdf52e541d9d28"),
            "isbn": "978-3-16-148999-9",
            "copies_sold": 720050
        },
        {
            "_id": ObjectId("56e31ce076cdf52e541d9d28"),
            "isbn": "978-3-16-148999-9",
            "copies_sold": 1000
        }
    ]
}

कुछ बातों पर ध्यान देना जरूरी है:

  1. इस मामले में "से" संग्रह, books_selling_dataतेज नहीं किया जा सकता है।
  2. "जैसा" फ़ील्ड ऊपर के उदाहरण के रूप में एक सरणी होगी।
  3. $ लुकिंग स्टेज पर "लोकलफिल्ड" और "फॉरेनफिल्ड" दोनों विकल्पों को मिलान के उद्देश्यों के लिए अशक्त माना जाएगा यदि वे अपने संबंधित संग्रह में मौजूद नहीं हैं ( $ लुकअप डॉक्स के बारे में एक आदर्श उदाहरण है)।

इसलिए, एक निष्कर्ष के रूप में, यदि आप दोनों संग्रहों को समेकित करना चाहते हैं, तो इस मामले में, बेची गई कुल प्रतियों के साथ एक सपाट प्रतियां_होल्ड फ़ील्ड, आपको थोड़ा अधिक काम करना होगा, शायद एक मध्यस्थ संग्रह का उपयोग करना होगा, जो तब, हो $ बाहर अंतिम संग्रह करने के लिए।


नमस्ते वहाँ, आप कृपया बता सकते हैं कि इस तरह से डेटा का प्रबंधन करने के लिए अनुकूलित तरीका क्या होगा: उपयोगकर्ता, file.files और file.chunks तीन संग्रह हैं, मैं एक विशिष्ट उपयोगकर्ता चाहता हूं कि इसकी प्रतिक्रिया में संबंधित सभी फ़ाइल संभव है? {"नाम": "बैटमैन", "ईमेल ':" bt@gmail.com "," फाइलें ": [{file1}, {file2}, {file3}, .... इत्यादि]
mfaisalhyder

उपरोक्त समाधान के लिए आधिकारिक दस्तावेज उदाहरण यहां देखे
Jakub Czaplicki

4
खैर, वास्तव में मेरे जवाब में पहले से ही आधिकारिक दस्तावेज के तीन लिंक थे। लेकिन वैसे भी आपके योगदान के लिए धन्यवाद। @JakubCzaplicki
ब्रूनो क्रेब्स

2
मुझे कुल मस्तिष्क की खराबी (सबसे अधिक संभावना है) हो सकती है, लेकिन $lookupसभी "लोकलफिल्ड" और "फॉरेनफिल्ड" के बराबर "आइसबीएन" दोनों में नहीं होना चाहिए? "_id" और "isbn" नहीं है?
14:01 बजे देव

13

अगर मोंगोडब में कोई बल्क इंसर्ट नहीं है, तो हम सभी ऑब्जेक्ट्स को लूप करते हैं small_collectionऔर उन्हें एक-एक करके अंदर डालते हैं big_collection:

db.small_collection.find().forEach(function(obj){ 
   db.big_collection.insert(obj)
});

db.colleciton.insert ([{}, {}, {}]) सरणियाँ सम्मिलित करें।
यंगुर

2
यह छोटे संग्रह के लिए ठीक काम करता है, लेकिन अनुक्रमित करने के लिए मत भूलना :) :)
सेबेस्टियन लॉबर

12

$ खोज के साथ बहुत बुनियादी उदाहरण।

db.getCollection('users').aggregate([
    {
        $lookup: {
            from: "userinfo",
            localField: "userId",
            foreignField: "userId",
            as: "userInfoData"
        }
    },
    {
        $lookup: {
            from: "userrole",
            localField: "userId",
            foreignField: "userId",
            as: "userRoleData"
        }
    },
    { $unwind: { path: "$userInfoData", preserveNullAndEmptyArrays: true }},
    { $unwind: { path: "$userRoleData", preserveNullAndEmptyArrays: true }}
])

यहाँ प्रयोग किया जाता है

 { $unwind: { path: "$userInfoData", preserveNullAndEmptyArrays: true }}, 
 { $unwind: { path: "$userRoleData", preserveNullAndEmptyArrays: true }}

के बजाय

{ $unwind:"$userRoleData"} 
{ $unwind:"$userRoleData"}

क्योंकि {$ खोलना: "$ userRoleData"} यह खाली या 0 परिणाम देगा यदि $ लुकिंग के साथ कोई मिलान रिकॉर्ड नहीं मिला।


11

एक 'SQL यूनिअन' फैशन में MongoDB में यूनियनों को करना एक ही प्रश्न में लुकअप के साथ-साथ एकत्रीकरण का उपयोग करना संभव है। यहाँ मैंने एक उदाहरण का परीक्षण किया है जो MongoDB 4.0 के साथ काम करता है:

// Create employees data for testing the union.
db.getCollection('employees').insert({ name: "John", type: "employee", department: "sales" });
db.getCollection('employees').insert({ name: "Martha", type: "employee", department: "accounting" });
db.getCollection('employees').insert({ name: "Amy", type: "employee", department: "warehouse" });
db.getCollection('employees').insert({ name: "Mike", type: "employee", department: "warehouse"  });

// Create freelancers data for testing the union.
db.getCollection('freelancers').insert({ name: "Stephany", type: "freelancer", department: "accounting" });
db.getCollection('freelancers').insert({ name: "Martin", type: "freelancer", department: "sales" });
db.getCollection('freelancers').insert({ name: "Doug", type: "freelancer", department: "warehouse"  });
db.getCollection('freelancers').insert({ name: "Brenda", type: "freelancer", department: "sales"  });

// Here we do a union of the employees and freelancers using a single aggregation query.
db.getCollection('freelancers').aggregate( // 1. Use any collection containing at least one document.
  [
    { $limit: 1 }, // 2. Keep only one document of the collection.
    { $project: { _id: '$$REMOVE' } }, // 3. Remove everything from the document.

    // 4. Lookup collections to union together.
    { $lookup: { from: 'employees', pipeline: [{ $match: { department: 'sales' } }], as: 'employees' } },
    { $lookup: { from: 'freelancers', pipeline: [{ $match: { department: 'sales' } }], as: 'freelancers' } },

    // 5. Union the collections together with a projection.
    { $project: { union: { $concatArrays: ["$employees", "$freelancers"] } } },

    // 6. Unwind and replace root so you end up with a result set.
    { $unwind: '$union' },
    { $replaceRoot: { newRoot: '$union' } }
  ]);

यहां बताया गया है कि यह कैसे काम करता है:

  1. अपने डेटाबेस aggregateके किसी भी संग्रह से तुरंत हटाएं जिसमें कम से कम एक दस्तावेज़ हो। यदि आप गारंटी नहीं दे सकते हैं कि आपके डेटाबेस का कोई भी संग्रह खाली नहीं होगा, तो आप इस मुद्दे को अपने डेटाबेस में बनाकर कुछ इस तरह का 'डमी' संग्रह बना सकते हैं जिसमें एक एकल खाली दस्तावेज़ हो, जो विशेष रूप से यूनियन क्वेरी करने के लिए होगा।

  2. अपनी पाइपलाइन का पहला चरण बनाएं { $limit: 1 }। यह संग्रह के सभी दस्तावेजों को पहले एक को छोड़कर छीन लेगा।

  3. एक $projectचरण का उपयोग करके शेष दस्तावेज़ के सभी क्षेत्रों को पट्टी करें :

    { $project: { _id: '$$REMOVE' } }
  4. आपके कुल में अब एक एकल, खाली दस्तावेज़ है। यह प्रत्येक संग्रह के लिए लुकअप जोड़ने का समय है जिसे आप एक साथ मिलाना चाहते हैं। आप उपयोग कर सकते हैं pipelineकुछ विशिष्ट छानने करने के लिए क्षेत्र, या छोड़ localFieldऔर foreignFieldअशक्त रूप में पूरे संग्रह मिलान करने के लिए।

    { $lookup: { from: 'collectionToUnion1', pipeline: [...], as: 'Collection1' } },
    { $lookup: { from: 'collectionToUnion2', pipeline: [...], as: 'Collection2' } },
    { $lookup: { from: 'collectionToUnion3', pipeline: [...], as: 'Collection3' } }
  5. अब आपके पास एक एकल दस्तावेज़ है जिसमें इस तरह के 3 सरणियाँ हैं:

    {
        Collection1: [...],
        Collection2: [...],
        Collection3: [...]
    }

    आप एकत्रीकरण ऑपरेटर $projectके साथ एक मंच का उपयोग करके उन्हें एक साथ एक एकल सरणी में विलय कर सकते हैं $concatArrays:

    {
      "$project" :
      {
        "Union" : { $concatArrays: ["$Collection1", "$Collection2", "$Collection3"] }
      }
    }
  6. अब आपके पास एक एकल दस्तावेज़ है, जिसमें एक ऐसा सरणी स्थित है जिसमें आपके संग्रह का संघ है। जो कुछ करना बाकी है, उसे अपने दस्तावेज़ को अलग-अलग दस्तावेज़ों में विभाजित करने के लिए एक $unwindऔर एक $replaceRootचरण जोड़ना है :

    { $unwind: "$Union" },
    { $replaceRoot: { newRoot: "$Union" } }
  7. Voilà। अब आपके पास एक परिणाम सेट है जिसमें वे संग्रह हैं जिन्हें आप एक साथ मिलाना चाहते थे। फिर आप इसे फ़िल्टर करने के लिए और चरण जोड़ सकते हैं, इसे क्रमबद्ध कर सकते हैं, स्किप () और सीमा () लागू कर सकते हैं। बहुत कुछ आप चाहते हैं।


प्रश्न "$ प्रोजेक्शन के लिए कम से कम एक आउटपुट फ़ील्ड की आवश्यकता है" संदेश के साथ विफल हो रहा है।
abhishek_ganta

@abhishek अगर आपको लगता है कि ऐसा इसलिए है क्योंकि आपने एक एकल प्रक्षेपण चरण में एकल दस्तावेज़ से सभी फ़ील्ड को हटाने का प्रयास किया है। MongoDB आपको ऐसा करने नहीं देगा। इसे हल करने के लिए आपको 2 क्रमिक अनुमानों को करने की आवश्यकता है, जहां पहला एक सब कुछ स्ट्रिप करता है, लेकिन _id, और दूसरा एक शेष _id स्ट्रिप्स करता है।
1919

@abhishek ने '$$ REMOVE' वैरिएबल का उपयोग करने वाले एकल में $ प्रोजेक्ट चरणों को बदलकर और भी सरल बना दिया है। मैंने एक ठोस उदाहरण भी जोड़ा है जिसे आप अपने क्वेरी परीक्षक में सीधे कॉपी और पेस्ट कर सकते हैं यह देखने के लिए कि यह काम करता है।
sboisse

@sboisse, यह समाधान छोटे संग्रहों के लिए काम करता है, हालाँकि, अगर मैं इसे बड़े संग्रहों पर करना चाहता हूँ, (100,000+ डॉक्स), तो मैं "संग्रह में दस्तावेज़ों का कुल आकार। डॉक्स में, यह बड़े मध्यवर्ती दस्तावेजों को बनाने से बचने के लिए $ लुक के बाद सीधे $ खोल देने का सुझाव देता है। मैं उस पद्धति का उपयोग करके इस समाधान को संशोधित करने में सफल नहीं रहा हूं। क्या आप इस मुद्दे में भाग गए हैं और उस पद्धति का उपयोग करना पड़ा है? डॉक्स से लिंक मैं इस बात से अवगत हूं : [लिंक] ( डॉक्स.mongodb.com/manual/core/aggregation-pipeline-optimization/… )
lucky7samson

@ lucky7samson दुर्भाग्य से जितना डेटा मुझे डील करना था, वह उतना बड़ा नहीं था। इसलिए मुझे उस समस्या का सामना नहीं करना पड़ा जिसका आप उल्लेख कर रहे हैं। मेरे मामले में मैं बाकी के साथ रिकॉर्ड्स को मर्ज करने से पहले देखने के लिए संग्रह पर फ़िल्टरिंग लागू कर सकता हूं, इसलिए संघ के लिए डेटा की मात्रा काफी कम थी।
sboisse

9

एकत्रीकरण में कई संग्रह के लिए कई $ लुकअप का उपयोग करें

क्वेरी:

db.getCollection('servicelocations').aggregate([
  {
    $match: {
      serviceLocationId: {
        $in: ["36728"]
      }
    }
  },
  {
    $lookup: {
      from: "orders",
      localField: "serviceLocationId",
      foreignField: "serviceLocationId",
      as: "orders"
    }
  },
  {
    $lookup: {
      from: "timewindowtypes",
      localField: "timeWindow.timeWindowTypeId",
      foreignField: "timeWindowTypeId",
      as: "timeWindow"
    }
  },
  {
    $lookup: {
      from: "servicetimetypes",
      localField: "serviceTimeTypeId",
      foreignField: "serviceTimeTypeId",
      as: "serviceTime"
    }
  },
  {
    $unwind: "$orders"
  },
  {
    $unwind: "$serviceTime"
  },
  {
    $limit: 14
  }
])

परिणाम:

{
    "_id" : ObjectId("59c3ac4bb7799c90ebb3279b"),
    "serviceLocationId" : "36728",
    "regionId" : 1.0,
    "zoneId" : "DXBZONE1",
    "description" : "AL HALLAB REST EMIRATES MALL",
    "locationPriority" : 1.0,
    "accountTypeId" : 1.0,
    "locationType" : "SERVICELOCATION",
    "location" : {
        "makani" : "",
        "lat" : 25.119035,
        "lng" : 55.198694
    },
    "deliveryDays" : "MTWRFSU",
    "timeWindow" : [ 
        {
            "_id" : ObjectId("59c3b0a3b7799c90ebb32cde"),
            "timeWindowTypeId" : "1",
            "Description" : "MORNING",
            "timeWindow" : {
                "openTime" : "06:00",
                "closeTime" : "08:00"
            },
            "accountId" : 1.0
        }, 
        {
            "_id" : ObjectId("59c3b0a3b7799c90ebb32cdf"),
            "timeWindowTypeId" : "1",
            "Description" : "MORNING",
            "timeWindow" : {
                "openTime" : "09:00",
                "closeTime" : "10:00"
            },
            "accountId" : 1.0
        }, 
        {
            "_id" : ObjectId("59c3b0a3b7799c90ebb32ce0"),
            "timeWindowTypeId" : "1",
            "Description" : "MORNING",
            "timeWindow" : {
                "openTime" : "10:30",
                "closeTime" : "11:30"
            },
            "accountId" : 1.0
        }
    ],
    "address1" : "",
    "address2" : "",
    "phone" : "",
    "city" : "",
    "county" : "",
    "state" : "",
    "country" : "",
    "zipcode" : "",
    "imageUrl" : "",
    "contact" : {
        "name" : "",
        "email" : ""
    },
    "status" : "ACTIVE",
    "createdBy" : "",
    "updatedBy" : "",
    "updateDate" : "",
    "accountId" : 1.0,
    "serviceTimeTypeId" : "1",
    "orders" : [ 
        {
            "_id" : ObjectId("59c3b291f251c77f15790f92"),
            "orderId" : "AQ18O1704264",
            "serviceLocationId" : "36728",
            "orderNo" : "AQ18O1704264",
            "orderDate" : "18-Sep-17",
            "description" : "AQ18O1704264",
            "serviceType" : "Delivery",
            "orderSource" : "Import",
            "takenBy" : "KARIM",
            "plannedDeliveryDate" : ISODate("2017-08-26T00:00:00.000Z"),
            "plannedDeliveryTime" : "",
            "actualDeliveryDate" : "",
            "actualDeliveryTime" : "",
            "deliveredBy" : "",
            "size1" : 296.0,
            "size2" : 3573.355,
            "size3" : 240.811,
            "jobPriority" : 1.0,
            "cancelReason" : "",
            "cancelDate" : "",
            "cancelBy" : "",
            "reasonCode" : "",
            "reasonText" : "",
            "status" : "",
            "lineItems" : [ 
                {
                    "ItemId" : "BNWB020",
                    "size1" : 15.0,
                    "size2" : 78.6,
                    "size3" : 6.0
                }, 
                {
                    "ItemId" : "BNWB021",
                    "size1" : 20.0,
                    "size2" : 252.0,
                    "size3" : 11.538
                }, 
                {
                    "ItemId" : "BNWB023",
                    "size1" : 15.0,
                    "size2" : 285.0,
                    "size3" : 16.071
                }, 
                {
                    "ItemId" : "CPMW112",
                    "size1" : 3.0,
                    "size2" : 25.38,
                    "size3" : 1.731
                }, 
                {
                    "ItemId" : "MMGW001",
                    "size1" : 25.0,
                    "size2" : 464.375,
                    "size3" : 46.875
                }, 
                {
                    "ItemId" : "MMNB218",
                    "size1" : 50.0,
                    "size2" : 920.0,
                    "size3" : 60.0
                }, 
                {
                    "ItemId" : "MMNB219",
                    "size1" : 50.0,
                    "size2" : 630.0,
                    "size3" : 40.0
                }, 
                {
                    "ItemId" : "MMNB220",
                    "size1" : 50.0,
                    "size2" : 416.0,
                    "size3" : 28.846
                }, 
                {
                    "ItemId" : "MMNB270",
                    "size1" : 50.0,
                    "size2" : 262.0,
                    "size3" : 20.0
                }, 
                {
                    "ItemId" : "MMNB302",
                    "size1" : 15.0,
                    "size2" : 195.0,
                    "size3" : 6.0
                }, 
                {
                    "ItemId" : "MMNB373",
                    "size1" : 3.0,
                    "size2" : 45.0,
                    "size3" : 3.75
                }
            ],
            "accountId" : 1.0
        }, 
        {
            "_id" : ObjectId("59c3b291f251c77f15790f9d"),
            "orderId" : "AQ137O1701240",
            "serviceLocationId" : "36728",
            "orderNo" : "AQ137O1701240",
            "orderDate" : "18-Sep-17",
            "description" : "AQ137O1701240",
            "serviceType" : "Delivery",
            "orderSource" : "Import",
            "takenBy" : "KARIM",
            "plannedDeliveryDate" : ISODate("2017-08-26T00:00:00.000Z"),
            "plannedDeliveryTime" : "",
            "actualDeliveryDate" : "",
            "actualDeliveryTime" : "",
            "deliveredBy" : "",
            "size1" : 28.0,
            "size2" : 520.11,
            "size3" : 52.5,
            "jobPriority" : 1.0,
            "cancelReason" : "",
            "cancelDate" : "",
            "cancelBy" : "",
            "reasonCode" : "",
            "reasonText" : "",
            "status" : "",
            "lineItems" : [ 
                {
                    "ItemId" : "MMGW001",
                    "size1" : 25.0,
                    "size2" : 464.38,
                    "size3" : 46.875
                }, 
                {
                    "ItemId" : "MMGW001-F1",
                    "size1" : 3.0,
                    "size2" : 55.73,
                    "size3" : 5.625
                }
            ],
            "accountId" : 1.0
        }, 
        {
            "_id" : ObjectId("59c3b291f251c77f15790fd8"),
            "orderId" : "AQ110O1705036",
            "serviceLocationId" : "36728",
            "orderNo" : "AQ110O1705036",
            "orderDate" : "18-Sep-17",
            "description" : "AQ110O1705036",
            "serviceType" : "Delivery",
            "orderSource" : "Import",
            "takenBy" : "KARIM",
            "plannedDeliveryDate" : ISODate("2017-08-26T00:00:00.000Z"),
            "plannedDeliveryTime" : "",
            "actualDeliveryDate" : "",
            "actualDeliveryTime" : "",
            "deliveredBy" : "",
            "size1" : 60.0,
            "size2" : 1046.0,
            "size3" : 68.0,
            "jobPriority" : 1.0,
            "cancelReason" : "",
            "cancelDate" : "",
            "cancelBy" : "",
            "reasonCode" : "",
            "reasonText" : "",
            "status" : "",
            "lineItems" : [ 
                {
                    "ItemId" : "MMNB218",
                    "size1" : 50.0,
                    "size2" : 920.0,
                    "size3" : 60.0
                }, 
                {
                    "ItemId" : "MMNB219",
                    "size1" : 10.0,
                    "size2" : 126.0,
                    "size3" : 8.0
                }
            ],
            "accountId" : 1.0
        }
    ],
    "serviceTime" : {
        "_id" : ObjectId("59c3b07cb7799c90ebb32cdc"),
        "serviceTimeTypeId" : "1",
        "serviceTimeType" : "nohelper",
        "description" : "",
        "fixedTime" : 30.0,
        "variableTime" : 0.0,
        "accountId" : 1.0
    }
}

1

मोंगोरेस्टोर में डेटाबेस में पहले से ही जो कुछ भी है उसके ऊपर संलग्न करने की यह विशेषता है, इसलिए इस व्यवहार का उपयोग दो संग्रह के संयोजन के लिए किया जा सकता है:

  1. संग्रही संग्रह १
  2. collection2.rename (collection1)
  3. mongorestore

अभी तक यह कोशिश नहीं की, लेकिन यह नक्शे की तुलना में तेजी से प्रदर्शन कर सकता है / दृष्टिकोण को कम कर सकता है।


1

शुरू करते हुए Mongo 4.4, हम नए $unionWithएकत्रीकरण चरण को $groupनए $accumulatorऑपरेटर के साथ जोड़कर एक एकत्रीकरण पाइपलाइन के भीतर इसे प्राप्त कर सकते हैं :

// > db.users.find()
//   [{ user: 1, name: "x" }, { user: 2, name: "y" }]
// > db.books.find()
//   [{ user: 1, book: "a" }, { user: 1, book: "b" }, { user: 2, book: "c" }]
// > db.movies.find()
//   [{ user: 1, movie: "g" }, { user: 2, movie: "h" }, { user: 2, movie: "i" }]
db.users.aggregate([
  { $unionWith: "books"  },
  { $unionWith: "movies" },
  { $group: {
    _id: "$user",
    user: {
      $accumulator: {
        accumulateArgs: ["$name", "$book", "$movie"],
        init: function() { return { books: [], movies: [] } },
        accumulate: function(user, name, book, movie) {
          if (name) user.name = name;
          if (book) user.books.push(book);
          if (movie) user.movies.push(movie);
          return user;
        },
        merge: function(userV1, userV2) {
          if (userV2.name) userV1.name = userV2.name;
          userV1.books.concat(userV2.books);
          userV1.movies.concat(userV2.movies);
          return userV1;
        },
        lang: "js"
      }
    }
  }}
])
// { _id: 1, user: { books: ["a", "b"], movies: ["g"], name: "x" } }
// { _id: 2, user: { books: ["c"], movies: ["h", "i"], name: "y" } }
  • $unionWithएकत्रीकरण पाइपलाइन में दस्तावेजों के भीतर दिए गए संग्रह से रिकॉर्ड को जोड़ती है। 2 यूनियन चरणों के बाद, हमारे पास पाइपलाइन के भीतर सभी उपयोगकर्ता, किताबें और फिल्में रिकॉर्ड हैं।

  • तब हम ऑपरेटर $groupद्वारा दस्तावेजों के कस्टम संचय की अनुमति देते $userहुए वस्तुओं का संग्रह और संचय करते हैं $accumulatorक्योंकि वे समूहबद्ध हो जाते हैं:

    • वे फ़ील्ड जिन्हें हम संचित करने में रुचि रखते हैं, के साथ परिभाषित किया गया है accumulateArgs
    • init उस समूह को परिभाषित करता है जिसे हम समूह तत्वों के रूप में संचित करेंगे।
    • accumulateसमारोह प्रदर्शन की अनुमति देता है एक रिकार्ड के साथ एक कस्टम कार्रवाई आदेश संचित राज्य का निर्माण करने में वर्गीकृत किया जा रहा है। उदाहरण के लिए, यदि आइटम को समूहीकृत किया जा रहा है book, तो फ़ील्ड परिभाषित है, तो हम अपडेट करते हैंbooks राज्य हिस्से को ।
    • mergeका उपयोग दो आंतरिक अवस्थाओं को मिलाने के लिए किया जाता है। इसका उपयोग केवल शार्प किए गए समूहों पर चलने वाले एकत्रीकरण के लिए किया जाता है या जब ऑपरेशन मेमोरी सीमा से अधिक हो जाता है।

क्या इसके लिए समान आउटपुट प्राप्त करना संभव है: 4.2.6 संस्करण
निक्सित पटेल

0

हां आप यह कर सकते हैं: आज जो मैंने लिखा है, यह उपयोगिता कार्य करें:

function shangMergeCol() {
  tcol= db.getCollection(arguments[0]);
  for (var i=1; i<arguments.length; i++){
    scol= db.getCollection(arguments[i]);
    scol.find().forEach(
        function (d) {
            tcol.insert(d);
        }
    )
  }
}

आप इस फ़ंक्शन को किसी भी संख्या के संग्रह में पास कर सकते हैं, पहला लक्ष्य एक होने वाला है। बाकी सभी संग्रह स्रोत हैं जिन्हें लक्ष्य एक में स्थानांतरित किया जाना है।


-1

सांकेतिक टुकड़ा। सौजन्य-एक सहित ढेर अतिप्रवाह पर कई पोस्ट।

 db.cust.drop();
 db.zip.drop();
 db.cust.insert({cust_id:1, zip_id: 101});
 db.cust.insert({cust_id:2, zip_id: 101});
 db.cust.insert({cust_id:3, zip_id: 101});
 db.cust.insert({cust_id:4, zip_id: 102});
 db.cust.insert({cust_id:5, zip_id: 102});

 db.zip.insert({zip_id:101, zip_cd:'AAA'});
 db.zip.insert({zip_id:102, zip_cd:'BBB'});
 db.zip.insert({zip_id:103, zip_cd:'CCC'});

mapCust = function() {
    var values = {
        cust_id: this.cust_id
    };
    emit(this.zip_id, values);
};

mapZip = function() {
    var values = {
    zip_cd: this.zip_cd
    };
    emit(this.zip_id, values);
};

reduceCustZip =  function(k, values) {
    var result = {};
    values.forEach(function(value) {
    var field;
        if ("cust_id" in value) {
            if (!("cust_ids" in result)) {
                result.cust_ids = [];
            }
            result.cust_ids.push(value);
        } else {
    for (field in value) {
        if (value.hasOwnProperty(field) ) {
                result[field] = value[field];
        }
         };  
       }
      });
       return result;
};


db.cust_zip.drop();
db.cust.mapReduce(mapCust, reduceCustZip, {"out": {"reduce": "cust_zip"}});
db.zip.mapReduce(mapZip, reduceCustZip, {"out": {"reduce": "cust_zip"}});
db.cust_zip.find();


mapCZ = function() {
    var that = this;
    if ("cust_ids" in this.value) {
        this.value.cust_ids.forEach(function(value) {
            emit(value.cust_id, {
                zip_id: that._id,
                zip_cd: that.value.zip_cd
            });
        });
    }
};

reduceCZ = function(k, values) {
    var result = {};
    values.forEach(function(value) {
        var field;
        for (field in value) {
            if (value.hasOwnProperty(field)) {
                result[field] = value[field];
            }
        }
    });
    return result;
};
db.cust_zip_joined.drop();
db.cust_zip.mapReduce(mapCZ, reduceCZ, {"out": "cust_zip_joined"}); 
db.cust_zip_joined.find().pretty();


var flattenMRCollection=function(dbName,collectionName) {
    var collection=db.getSiblingDB(dbName)[collectionName];

    var i=0;
    var bulk=collection.initializeUnorderedBulkOp();
    collection.find({ value: { $exists: true } }).addOption(16).forEach(function(result) {
        print((++i));
        //collection.update({_id: result._id},result.value);

        bulk.find({_id: result._id}).replaceOne(result.value);

        if(i%1000==0)
        {
            print("Executing bulk...");
            bulk.execute();
            bulk=collection.initializeUnorderedBulkOp();
        }
    });
    bulk.execute();
};


flattenMRCollection("mydb","cust_zip_joined");
db.cust_zip_joined.find().pretty();

-2

आपको अपनी एप्लिकेशन परत में ऐसा करना होगा। यदि आप ORM का उपयोग कर रहे हैं, तो यह अन्य संग्रह में मौजूद संदर्भों को खींचने के लिए एनोटेशन (या कुछ समान) का उपयोग कर सकता है। मैंने केवल मॉर्फिया के साथ काम किया है , और @Referenceएनोटेशन को संदर्भित किए जाने पर संदर्भित इकाई प्राप्त होती है, इसलिए मैं इसे कोड में स्वयं करने से बचने में सक्षम हूं।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.