2015-10-22 11 views
5

के साथ न्यूनतम, नेस्टेड ऑब्जेक्ट में न्यूनतम खोजें, मेरे पास minimum query और maximum query नीचे नमूना डेटा सेट पर एक प्रश्न है। में मेरे मामले फ़ील्ड नाम गतिशील हैं, नीचे दिए गए product_1, product_2 ...मोंगोडीबी: डायनामिक फ़ील्ड नाम

{ 
    "_id" : NumberLong(540), 
    "product_1" : { 
      "orderCancelled" : 0, 
      "orderDelivered" : 6 
    }, 
    "product_2" : { 
      "orderCancelled" : 3, 
      "orderDelivered" : 16 
    }, 
    "product_3" : { 
      "orderCancelled" : 5, 
      "orderDelivered" : 11 
    } 
} 

मैं एक विचार नहीं मिल रहा है मैं कैसे मोंगो में ऐसा कर सकते हैं जहां फ़ील्ड नाम गतिशील हैं, भविष्य में इसका मतलब है की तरह वहाँ अन्य हो सकता है उत्पाद product_4 और product_5 के समान id के लिए भी बनाए जाते हैं।

मैं एक प्रश्न जो मुझे orderCancelled के लिए orderDelivered के लिए न्यूनतम मूल्य और अधिकतम मूल्य देता है, ऊपर दस्तावेज़ परिणाम में उदाहरण orderDelivered:16 & orderCancelled:0 हो जाएगा के लिए के रूप में की जरूरत है।
किसी भी विचार के लिए धन्यवाद।

+0

क्यों नहीं आप अपने उत्पादों को एक सरणी में रख सकता हूं? –

+0

@DmytroShevchenko मैं तुम्हें नहीं मिला था। दरअसल एक दूसरे मामले में मैं 'ऑर्डर डिलीवरेड' के लिए 'उत्पाद नाम' द्वारा गिनती भी दे सकता हूं। वैसे आपके मामले में डिजाइन क्या होगा? – Shams

+0

कृपया मेरे उत्तर में डेटा संरचना का उदाहरण देखें। क्या आप 'उत्पाद नाम' द्वारा 'ऑर्डर डिलीवरेड' के लिए गिनती से क्या मतलब बता सकते हैं? –

उत्तर

1

आपको अपने दस्तावेज़ के पुनर्गठन करना चाहिए ताकि सभी उत्पाद दस्तावेजों एक सरणी में हैं:

{ 
    "_id": NumberLong(540), 
    products: [ 
     { 
      "name": "product_1", 
      "orderCancelled": 0, 
      "orderDelivered": 6 
     }, 
     { 
      "name": "product_2", 
      "orderCancelled": 3, 
      "orderDelivered": 16 
     }, 
     { 
      "name": "product_3", 
      "orderCancelled": 5, 
      "orderDelivered": 11 
     } 
    ] 
} 

तो फिर तुम इस तरह सामान्य अधिकतम/मिनट क्वेरी भेज कर सकेंगे:

db.test.aggregate([ 
    { 
     $match: { "_id" : NumberLong(540) } 
    }, 
    { 
     $unwind: "$products" 
    }, 
    { 
     $group: { 
      _id: "$_id", 
      minDelivered: { $min: "$products.orderDelivered" }, 
      maxCancelled: { $max: "$products.orderCancelled" } 
     } 
    } 
]) 
+0

दस्तावेजों की संरचना को बदलने का तरीका दिखाने के बारे में क्या? – styvane

+2

@ user3100115 मौजूदा डेटा को एक अलग उपकरण का उपयोग करके बदला जाना है। मेरा मानना ​​है कि इस तरह के एक उपकरण पर चर्चा करना यहां विषय से दूर होगा। –

+0

नहीं, आप इसे – styvane

2

आप उन्हें अद्यतन करके अपने दस्तावेज़ संरचना को बदलने की जरूरत है। .forEach विधि का उपयोग करके प्रत्येक दस्तावेज़ के माध्यम से आपको लूप की आवश्यकता होगी $unset सभी फ़ील्ड का नाम जो product_ से शुरू होता है। वहां से आपको products नए फ़ील्ड जोड़ने की आवश्यकता होगी जो $set अद्यतन ऑपरेटर का उपयोग कर उत्पादों की सरणी है। कहा जा रहा है कि आप अधिकतम दक्षता के लिए अपने दस्तावेज़ों को अद्यतन करने के "bulk" संचालन का उपयोग करना चाहिए

var bulkOp = db.collection.initializeOrderedBulkOp(); 
var count = 0; 
db.collection.find().forEach(function(doc) { 
    var allproducts = []; 
    for(var key in doc) { 
     if(Object.prototype.hasOwnProperty.call(doc, key) && /^product_\d+/.test(key)) { 
      var product = {}; 
      product["name"] = key;  
      product["orderCancelled"] = doc[key]["orderCancelled"]; 
      product["orderDelivered"] = doc[key]["orderDelivered"]; 
      allproducts.push(product); 
      var unsetField = {}; 
      unsetField[key] = ""; 
      bulkOp.find({"_id": doc._id}).update({ "$unset": unsetField }); 
     }; 
     count++; 
    }; 
    bulkOp.find({"_id": doc._id}).update({ 
     "$set": { "products": allproducts } 
    }); 
    count++; 
    if(count % 500 === 0) { 
     // Execute per 500 operations and re-init 
     bulkOp.execute(); 
     bulkOp = db.collection.initializeOrderedBulkOp(); 
    } 
}) 

// clean up queues 

if(count > 0) { 
    bulkOp.execute(); 
} 

आपके दस्तावेज़ अब इस तरह दिखेगा:

{ 
     "_id" : NumberLong(542), 
     "products" : [ 
       { 
         "name" : "product_1", 
         "orderCancelled" : 0, 
         "orderDelivered" : 6 
       }, 
       { 
         "name" : "product_2", 
         "orderCancelled" : 3, 
         "orderDelivered" : 16 
       }, 
       { 
         "name" : "product_3", 
         "orderCancelled" : 5, 
         "orderDelivered" : 11 
       } 
     ] 
} 

फिर .aggregate() पद्धति का उपयोग करके अपने एकत्रीकरण क्वेरी आता है:

db.collection.aggregate([ 
    { "$match": { "_id": 542 } }, 
    { "$unwind": "$products" }, 
    { "$group": { 
     "_id": "$_id", 
     "maxOrderCancelled": { "$max": "$products.orderCancelled"}, 
     "minOrderDelivvered": { "$min": "$products.orderDelivered"} 
    }} 
]) 

कौन सा रिटर्न:

{ "_id" : NumberLong(542), "maxOrderCancelled" : 5, "minOrderDelivvered" : 6 } 

version 3.2 से आप $max और $min अपने $project चरण में जो यह करने के लिए एक और अधिक बेहतर तरीके से उपयोग कर सकते हैं क्योंकि वहाँ $unwind पहली बार अपने सरणी के लिए कोई जरूरत नहीं।

db.collection.aggregate([ 
    { "$match": { "_id": 542 } }, 
    { "$project": { 
     "maxOrderCancelled": { 
      "$max": { 
       "$map": { 
        "input": "$products", 
        "as": "order", 
        "in": "$$orc.orderCancelled" 
       } 
      } 
     }, 
     "minOrderDelivered": { 
      "$min": { 
       "$map": { 
        "input": "$products", 
        "as": "orc", 
        "in": "$$orc.orderDelivered" 
       } 
      } 
     } 
    }} 
]) 

कौन सा पैदावार:

{ "_id" : NumberLong(542), "maxOrderCancelled" : 5, "minOrderDelivered" : 6 } 
संबंधित मुद्दे