2013-03-19 5 views
14

मैं मूल्यांकन कर रहा हूं कि मोंगोडीबी एकत्रीकरण ढांचा हमारी आवश्यकताओं के अनुरूप कितना अच्छा है क्योंकि हम वर्तमान में SQL सर्वर के शीर्ष पर चल रहे हैं।मोंगोडब एकत्रीकरण ढांचे में केस-स्टेटमेंट निष्पादित करना

मैं निम्नलिखित छद्म रिकॉर्ड (एक एसक्यूएल तालिका में और एक पूर्ण दस्तावेज के रूप में स्तंभों के रूप में मॉडलिंग की एक MongoDB संग्रह में) कहो

{ 
    name: 'A', 
    timespent: 100, 
}, 
{ 
    name: 'B', 
    timespent: 200, 
}, 
{ 
    name: 'C', 
    timespent: 300, 
}, 
{ 
    name: 'D', 
    timespent: 400, 
}, 
{ 
    name: 'E', 
    timespent: 500, 
} 

मैं चाहता हूँ: मैं एक कठिन समय एक विशिष्ट पूछताछ हो रही है समय सीमा क्षेत्र को श्रेणियों में समूहित करने और घटनाओं की गिनती करने के लिए, इसलिए मुझे उदाहरण मिलेगा निम्नलिखित छद्म रिकॉर्ड:

results{ 
    0-250: 2, 
    250-450: 2, 
    450-650: 1 
} 

ध्यान दें कि इन सीमाओं (250, 450 और 650) गतिशील हैं और संभावना उपयोगकर्ता द्वारा समय के साथ बदल दिया जाएगा।

select range, COUNT(*) as total from (
select case when Timespent <= 250 then '0-250' 
when Timespent <= 450 then '200-450' 
else '450-600' end as range 
from TestTable) as r 
group by r.range 

फिर, ध्यान दें कि यह एसक्यूएल विशिष्ट श्रेणी किसी एक समय में उपलब्ध फिट करने के लिए हमारे एप्लिकेशन द्वारा गतिशील रूप से निर्माण किया है: एसक्यूएल में हम कुछ इस तरह के साथ परिणाम निकाले।

मैं ऐसे क्वेरी करने MongoDB एकत्रीकरण ढांचे में उचित निर्माणों को खोजने के लिए संघर्ष कर रहा हूँ। मैं पाइपलाइन में एक $ मैच डालकर एक ही श्रेणी के परिणामों के लिए पूछताछ कर सकता हूं (यानी एक सिंगल रेंज का परिणाम प्राप्त करना) लेकिन मैं सभी श्रेणियों और उनकी गणनाओं को एक पाइपलाइन क्वेरी में निकालने का तरीका नहीं समझ सकता।

+0

यह लिंक आपकी मदद करेगा http://stackoverflow.com/questions/8945766/mongodb-mysql-sum-case-when-equivalent/21700596#21700596 –

+1

http://www.codefari.com/2015 /08/case-statement-in-mongodb-query.html लिंक से ऊपर आपको – Singh

उत्तर

28

aggregation framework में "केस" एसक्यूएल कथन के अनुरूप क्या है, $ cond cond ऑपरेटर है (manual देखें)। $ cond कथन कथन को "कब-फिर" और "अन्य" अनुकरण करने के लिए घोंसला दिया जा सकता है, लेकिन मैंने एक और दृष्टिकोण चुना है, क्योंकि इसे पढ़ना आसान है (और उत्पन्न करने के लिए, नीचे देखें): मैं लिखने के लिए $ concat ऑपरेटर का उपयोग करूंगा श्रेणी स्ट्रिंग, जो तब समूह कुंजी के रूप में कार्य करता है।

दिया संग्रह के लिए

तो:

db.xx.find() 
{ "_id" : ObjectId("514919fb23700b41723f94dc"), "name" : "A", "timespent" : 100 } 
{ "_id" : ObjectId("514919fb23700b41723f94dd"), "name" : "B", "timespent" : 200 } 
{ "_id" : ObjectId("514919fb23700b41723f94de"), "name" : "C", "timespent" : 300 } 
{ "_id" : ObjectId("514919fb23700b41723f94df"), "name" : "D", "timespent" : 400 } 
{ "_id" : ObjectId("514919fb23700b41723f94e0"), "name" : "E", "timespent" : 500 } 

कुल (hardcoded) इस तरह दिखता है:

db.xx.aggregate([ 
    { $project: { 
    "_id": 0, 
    "range": { 
     $concat: [{ 
     $cond: [ { $lte: ["$timespent", 250] }, "range 0-250", "" ] 
     }, { 
     $cond: [ { $and: [ 
      { $gte: ["$timespent", 251] }, 
      { $lt: ["$timespent", 450] } 
     ] }, "range 251-450", "" ] 
     }, { 
     $cond: [ { $and: [ 
      { $gte: ["$timespent", 451] }, 
      { $lt: ["$timespent", 650] } 
     ] }, "range 450-650", "" ] 
     }] 
    } 
    }}, 
    { $group: { _id: "$range", count: { $sum: 1 } } }, 
    { $sort: { "_id": 1 } }, 
]); 

और परिणाम है:

{ 
    "result" : [ 
     { 
      "_id" : "range 0-250", 
      "count" : 2 
     }, 
     { 
      "_id" : "range 251-450", 
      "count" : 2 
     }, 
     { 
      "_id" : "range 450-650", 
      "count" : 1 
     } 
    ], 
    "ok" : 1 
} 

आदेश उत्पन्न करने के लिए कुल आदेश, आपको JSON ऑब्जेक्ट के रूप में "रेंज" प्रोजेक्शन बनाना होगा (या आप एक स्ट्रिंग उत्पन्न कर सकते हैं और तो JSON.parse (स्ट्रिंग))

जनरेटर इस तरह दिखता है का उपयोग करें:

var ranges = [ 0, 250, 450, 650 ]; 
var rangeProj = { 
    "$concat": [] 
}; 

for (i = 1; i < ranges.length; i++) { 
    rangeProj.$concat.push({ 
    $cond: { 
     if: { 
     $and: [{ 
      $gte: [ "$timespent", ranges[i-1] ] 
     }, { 
      $lt: [ "$timespent", ranges[i] ] 
     }] 
     }, 
     then: "range " + ranges[i-1] + "-" + ranges[i], 
     else: "" 
    } 
    }) 
} 

db.xx.aggregate([{ 
    $project: { "_id": 0, "range": rangeProj } 
}, { 
    $group: { _id: "$range", count: { $sum: 1 } } 
}, { 
    $sort: { "_id": 1 } 
}]); 

जो जैसा कि ऊपर एक ही परिणाम वापस आ जाएगी।

+0

इस उत्तर के लिए धन्यवाद कर सकता है। मैंने कभी भी कंसल्ट के बारे में सोचा नहीं होगा, लेकिन यह निश्चित रूप से कुछ चीजों को सरल बनाता है। –

+1

धन्यवाद संक्षिप्त और प्रभावी उत्तर .. अधिक http://www.codefari.com/2015/08/case-statement-in-mongodb-query.html – Singh

+0

जबकि यह उत्तर प्रश्न के विशेष मामले को हल करता है, ध्यान दें कि यह दृष्टिकोण केवल अनन्य स्थितियों का समर्थन करता है। यदि कुछ परिणाम 1 से अधिक समूह में आते हैं, तो उन्हें उनमें से प्रत्येक में सम्मिलित नहीं किया जाएगा, बल्कि एक अतिरिक्त समूह '' ' – ArnauOrriols

5

मोंगोडीबी 3.4 से शुरू करना हम ऑपरेटर का उपयोग $project चरण में एक बहु-स्विच स्टेटमेंट करने के लिए कर सकते हैं।

$group पाइपलाइन ऑपरेटर समूह "रेंज" द्वारा दस्तावेज समूह और $sum संचयक ऑपरेटर का उपयोग करके प्रत्येक समूह के लिए "गिनती" वापस कर देता है।

db.collection.aggregate(
    [ 
     { "$project": { 
      "range": { 
       "$switch": { 
        "branches": [ 
         { 
          "case": { "$lte": [ "$timespent", 250 ] }, 
          "then": "0-250" 
         }, 
         { 
          "case": { 
           "$and": [ 
            { "$gt": [ "$timespent", 250 ] }, 
            { "$lte": [ "$timespent", 450 ] } 
           ] 
          }, 
          "then": "251-450" 
         }, 
         { 
          "case": { 
           "$and": [ 
            { "$gt": [ "$timespent", 450 ] }, 
            { "$lte": [ "$timespent", 650 ] } 
           ] 
          }, 
          "then": "451-650" 
         } 
        ], 
        "default": "650+" 
       } 
      } 
     }}, 
     { "$group": { 
      "_id": "$range", 
      "count": { "$sum": 1 } 
     }} 
    ] 
) 

हमारे संग्रह में निम्नलिखित दस्तावेजों के साथ

,

{ "_id" : ObjectId("514919fb23700b41723f94dc"), "name" : "A", "timespent" : 100 }, 
{ "_id" : ObjectId("514919fb23700b41723f94dd"), "name" : "B", "timespent" : 200 }, 
{ "_id" : ObjectId("514919fb23700b41723f94de"), "name" : "C", "timespent" : 300 }, 
{ "_id" : ObjectId("514919fb23700b41723f94df"), "name" : "D", "timespent" : 400 }, 
{ "_id" : ObjectId("514919fb23700b41723f94e0"), "name" : "E", "timespent" : 500 } 

हमारे क्वेरी पैदावार:

{ "_id" : "451-650", "count" : 1 } 
{ "_id" : "251-450", "count" : 2 } 
{ "_id" : "0-250", "count" : 2 } 

हम पाइपलाइन तरह हमारे दस्तावेज़ में $sort चरण जोड़ने के लिए चाहते हो सकता है सीमा से लेकिन यह केवल "श्रेणी के प्रकार के कारण lexicographic order में दस्तावेज़ों को सॉर्ट करेगा "।

संबंधित मुद्दे