2012-10-08 11 views
13

MongoDB में आउटपुट स्वरूपण के लिए कुल कार्य कितना लचीला है?

डाटा प्रारूप:

{ 
     "_id" : ObjectId("506ddd1900a47d802702a904"), 
     "port_name" : "CL1-A", 
     "metric" : "772.0", 
     "port_number" : "0", 
     "datetime" : ISODate("2012-10-03T14:03:00Z"), 
     "array_serial" : "12345" 
} 

अभी मैं दिनांक समय, मैट्रिक्स की एक सरणी की एक सरणी वापस जाने के लिए इस एकीकृत फ़ंक्शन का उपयोग कर रहा है, और एक गिनती:

{$match : { 'array_serial' : array, 
          'port_name' : { $in : ports}, 
          'datetime' : { $gte : from, $lte : to} 
         } 
       }, 
       {$project : { port_name : 1, metric : 1, datetime: 1}}, 
       {$group : { _id : "$port_name", 
          datetime : { $push : "$datetime"}, 
          metric : { $push : "$metric"}, 
          count : { $sum : 1}}} 

कौन सा अच्छा है, और बहुत तेज़, लेकिन आउटपुट को प्रारूपित करने का कोई तरीका है, इसलिए प्रति दिन/मीट्रिक प्रति एक सरणी है? इस तरह:

[ 
    { 
     "_id" : "portname", 
     "data" : [ 
       ["2012-10-01T00:00:00.000Z", 1421.01], 
       ["2012-10-01T00:01:00.000Z", 1361.01], 
       ["2012-10-01T00:02:00.000Z", 1221.01] 
       ] 
    } 
] 

यह फ्रंट-एंड को बहुत सरल बना देगा क्योंकि यह चार्ट कोड अपेक्षा करता है।

+0

मतलब समय मैं उत्पादन हो रही है और वस्तुओं के माध्यम से पाशन और उन्हें गठबंधन करने के लिए अंडरस्कोर के 'zip' समारोह का उपयोग कर में, यह बहुत भूमि के ऊपर जोड़ने के लिए प्रतीत नहीं होता। –

उत्तर

16

समेकन फ्रेमवर्क के साथ मूल्यों की एक सरणी में दो फ़ील्ड जोड़ना संभव है, लेकिन निश्चित रूप से यह उतना सरल नहीं है जितना यह हो सकता है (कम से कम मोंगोडीबी 2.2.0 पर)।

यहाँ एक उदाहरण है:

db.metrics.aggregate(

    // Find matching documents first (can take advantage of index) 
    { $match : { 
     'array_serial' : array, 
     'port_name' : { $in : ports}, 
     'datetime' : { $gte : from, $lte : to} 
    }}, 

    // Project desired fields and add an extra $index for # of array elements 
    { $project: { 
     port_name: 1, 
     datetime: 1, 
     metric: 1, 
     index: { $const:[0,1] } 
    }}, 

    // Split into document stream based on $index 
    { $unwind: '$index' }, 

    // Re-group data using conditional to create array [$datetime, $metric] 
    { $group: { 
     _id: { id: '$_id', port_name: '$port_name' }, 
     data: { 
      $push: { $cond:[ {$eq:['$index', 0]}, '$datetime', '$metric'] } 
     }, 
    }}, 

    // Sort results 
    { $sort: { _id:1 } }, 

    // Final group by port_name with data array and count 
    { $group: { 
     _id: '$_id.port_name', 
     data: { $push: '$data' }, 
     count: { $sum: 1 } 
    }} 
) 
+0

आह! मुझे नहीं पता था कि $ समूह को एक से अधिक बार बुलाया जा सकता है। मैं इसे आज़मा दूंगा, धन्यवाद! –

+0

बचाव के लिए धन्यवाद, स्टेनी। :) –

+0

'$ const 'ठीक है? ऐसा प्रतीत नहीं होता है। – maxdec

1

$ पुश के बिना समेकन ढांचे में बिल्डिंग सरणी और $ addToSet ऐसा कुछ है जो कम होने लगता है। मैंने इसे पहले काम करने की कोशिश की है, और असफल रहा है। यह भयानक हो सकता है अगर तुम सिर्फ कर सकता है:

data : {$push: [$datetime, $metric]} 

$group में है, लेकिन वह काम नहीं करता।

इसके अलावा, इमारत "शाब्दिक" इस तरह की वस्तुओं से काम नहीं करता:

data : {$push: {literal:[$datetime, $metric]}} 
or even data : {$push: {literal:$datetime}} 

मुझे आशा है कि वे अंततः डेटा की इस तरह की मालिश से कुछ बेहतर तरीके के साथ आने के।

+0

ये सही तरीके हैं जिनकी मैंने कोशिश की, मैं बस यह मान रहा था कि यह काम करेगा। मुझे नहीं लगता :( –

2

MongoDB 2.6 $map, जो सरणी स्थानांतरण के एक सरल फार्म की अनुमति देता है शुरू करने से इस एक बहुत आसान बना दिया:

db.metrics.aggregate([ 
    { "$match": { 
     "array_serial": array, 
     "port_name": { "$in": ports}, 
     "datetime": { "$gte": from, "$lte": to } 
    }}, 
    { "$group": { 
     "_id": "$port_name", 
     "data": { 
      "$push": { 
       "$map": { 
        "input": [0,1], 
        "as": "index", 
        "in": { 
         "$cond": [ 
          { "$eq": [ "$$index", 0 ] }, 
          "$datetime", 
          "$metric" 
         ] 
        } 
       } 
      } 
     }, 
     "count": { "$sum": 1 } 
    }} 
]) 

कहाँ दृष्टिकोण की तरह $unwind के साथ, आप दो मानों वाले मानचित्र संचालन के लिए "इनपुट" के रूप में एक सरणी प्रदान करते हैं और फिर उन मानों को उन फ़ील्ड मानों के साथ प्रतिस्थापित करते हैं जिन्हें आपके माध्यम से चाहते हैंऑपरेशन।

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

0

आप $arrayElemAt साथ $zip ऑपरेटर का उपयोग कर सकते हैं 3,4

$zip में मानों की सरणी का निर्माण करने के datetime और metrics की एक सरणी बनाने के लिए।

कुछ की तरह

db.collection.aggregate([ { 
    "$match": { 
     "array_serial": array, 
     "port_name": { 
     "$in": ports 
     }, 
     "datetime": { 
     "$gte": from, 
     "$lte": to 
     } 
    } 
    }, 
    { 
    "$group": { 
     "_id": "$port_name", 
     "data": { 
     "$push": { 
      "$arrayElemAt": [ 
      { 
       "$zip": { 
       "inputs": [ 
        [ 
        "$datetime" 
        ], 
        [ 
        "$metric" 
        ] 
       ] 
       } 
      }, 
      0 
      ] 
     } 
     }, 
     "count": { 
     "$sum": 1 
     } 
    } 
    } 
]) 
संबंधित मुद्दे