2014-06-30 5 views
7

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

_id: P1 
    entities: [{type: A, val: X}, {type: B, val: X}, {type: A, val: Y}] 
    ... 

मैं $ करना चाहते तनाव कम और $ इन संस्थाओं परियोजना ताकि तरह एक संरचना मिल:

_id: P1 
    A: [X] 
    B: [] 
_id: P1 
    A: [Y] 
    B: [] 
_id: P1 
    A: [] 
    B: [X] 

तो मैं ए या बी या दोनों से एक समूह प्रदर्शन कर सकते हैं मैं एक संरचना इस प्रकार है यानी

$group: { 
    _id: { 
     A: $A, 
     B: $B 
    } 
    count: {$sum : 1} 

मैंने सोचा कि मैं बस कर सकता है:

$unwind: $entities 
$project: { 
    id: §id 
    A: {"$cond":[{"$eq":["$type","A"]},"$code"]} 
    B: {"$cond":[{"$eq":["$type","B"]},"$code"]} 
} 
$group: { 
    _id: "$id" 
    A: {$addToSet : "$A"} 
} 
01 क्योंकि मैं किसी और पर कुछ भी नहीं ऐसा नहीं कर सकते और मैं एक सशर्त अंदर $ धक्का उपयोग करने के लिए प्रबंधन नहीं किया

या की तरह

$unwind: $entities 
$group: { 
    _id: "$id" 
    A: {"$cond":[{"$eq":["$type","A"]},$push: "$code", null]} 
    ... 
} 

है कि कुछ में असफल रहने लेकिन दोनों संस्करणों असफल। निकटतम मुझे मिल प्रकार के आधार पर परियोजना है, लेकिन बाद से मैं एक तरह से क्षेत्र के लिए कुछ भी जोड़ने की नहीं है जब वहाँ कोई मुकाबला नहीं था नहीं मिल सकता है, मैं अंत:

_id: P1 
    A: [X,null,Y] 
    B: [null,X,null] 

जो गिनती को खराब करता। मेरा दूसरा विचार शून्य को हटाने के लिए सरणी फ़िल्टर करना था। लेकिन मुझे इकाइयों को हटाने का कोई रास्ता नहीं मिला, क्योंकि फिर से $ cond मुझे खाली/"कुछ भी नहीं" अन्य मामला निर्दिष्ट करने नहीं देगा।

मैं एक यह आवश्यक प्रकार के मिलान के साथ प्रकार और सामग्री द्वारा समूह के साथ काम कर सकता है, लेकिन क्योंकि मैं कई प्रकार और मनमाने ढंग से एक समूहीकरण पेड़ में जिसके परिणामस्वरूप समूह हैं, यह बहुत जटिल हो सकता है महसूस कर रही। विचारों या गलतियों के संकेतों का बहुत स्वागत है।

धन्यवाद

संपादित करें: समाधान को स्वीकार कर लिया anwser

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

{$project:{ 
    A: {$cond: [ 
     {$eq: ["$A", [false]]}, 
     ["N/A"], 
     "$A" 
    ]}, 
    B: {$cond: [ 
     {$eq: ["$B", [false]]}, 
     ["N/A"], 
     "$B" 
    ]}, 
}}, 
{ "$unwind": "$A" }, 
{ "$match": { "A": { "$ne": false } } }, 
{ "$group": { 
    "_id": "$_id", 
    "A": { "$push": "$A" }, 
    "B": { "$first": "$B" } 
}}, 
{ "$unwind": "$B" }, 
{ "$match": { "B": { "$ne": false } } }, 
{ "$group": { 
    "_id": "$_id", 
    "A": { "$first": "$A" }, 
    "B": { "$push": "$B" } 
}} 
+2

आपका _desired_ परिणाम क्या है? –

उत्तर

13

आप सही रास्ते पर लग रहा था, वहाँ सशर्त से false के उन मूल्यों को दूर करने के लिए सिर्फ अलग अलग दृष्टिकोण हैं। आप इसे कुछ भी वापस नहीं कर सकते हैं, लेकिन आप उन मूल्यों से छुटकारा पा सकते हैं जिन्हें आप नहीं चाहते हैं।

यदि आप वास्तव में "सेट" चाहते हैं और आपके पास MongoDB 2 है।$project अंदर $map ऑपरेटर का उपयोग

db.entities.aggregate([ 
    { "$unwind": "$entities" }, 
    { "$group": { 
     "_id": "$_id", 
     "A": { 
      "$addToSet": { 
       "$cond": [ 
        { "$eq": [ "$entities.type", "A" ] }, 
        "$entities.val", 
        false 
       ] 
      } 
     }, 
     "B": { 
      "$addToSet": { 
       "$cond": [ 
        { "$eq": [ "$entities.type", "B" ] }, 
        "$entities.val", 
        false 
       ] 
      } 
     } 
    }}, 
    { "$project": { 
     "A": { 
      "$setDifference": [ "$A", [false] ] 
     }, 
     "B": { 
      "$setDifference": [ "$B", [false] ] 
     } 
    }} 
]) 

या बस के रूप में एक कदम:: 6 या अधिक से अधिक उपलब्ध है, तो आप मूल रूप से बाहर false मूल्यों $setDifference का उपयोग कर फ़िल्टर कर

db.entities.aggregate([ 
    {"$project": { 
     "A": { 
      "$setDifference": [ 
       { 
        "$map": { 
         "input": "$entities", 
         "as": "el", 
         "in": { 
          "$cond": [ 
           { "$eq": [ "$$el.type", "A" ] }, 
           "$$el.val", 
           false 
          ] 
         } 
        } 
       }, 
       [false] 
      ] 
     }, 
     "B": { 
      "$setDifference": [ 
       { 
        "$map": { 
         "input": "$entities", 
         "as": "el", 
         "in": { 
          "$cond": [ 
           { "$eq": [ "$$el.type", "B" ] }, 
           "$$el.val", 
           false 
          ] 
         } 
        } 
       }, 
       [false] 
      ] 
     } 
    }} 
]) 

या अन्यथा सामान्य $unwind और $match के साथ रहना ऑपरेटर इन्हें फ़िल्टर करने के लिए:

db.entities.aggregate([ 
    { "$unwind": "$entities" }, 
    { "$group": { 
     "_id": "$_id", 
     "A": { 
      "$push": { 
       "$cond": [ 
        { "$eq": [ "$entities.type", "A" ] }, 
        "$entities.val", 
        false 
       ] 
      } 
     }, 
     "B": { 
      "$push": { 
       "$cond": [ 
        { "$eq": [ "$entities.type", "B" ] }, 
        "$entities.val", 
        false 
       ] 
      } 
     } 
    }}, 
    { "$unwind": "$A" }, 
    { "$match": { "A": { "$ne": false } } }, 
    { "$group": { 
     "_id": "$_id", 
     "A": { "$push": "$A" }, 
     "B": { "$first": "$B" } 
    }}, 
    { "$unwind": "$B" }, 
    { "$match": { "B": { "$ne": false } } }, 
    { "$group": { 
     "_id": "$_id", 
     "A": { "$first": "$A" }, 
     "B": { "$push": "$B" } 
    }} 
]) 

अद्वितीय सरणी के लिए $push या सामान्य सेट के लिए $addToSet का उपयोग करना।

+1

बहुत बढ़िया awnser धन्यवाद लाखों :) $ setDifference ऑपरेटर सही होगा (मैंने इसे नहीं देखा था), लेकिन दुख की बात है कि हम mongo 2.6 नहीं चल रहे हैं। Grr .. मैंने थोड़ा संस्करण संपादित करने के साथ दूसरे संस्करण का उपयोग किया (भविष्य के संदर्भ के लिए मूल प्रश्न का संपादन देखें) – user1437515

+0

क्वेरी इतनी जटिल हो जाती है कि परिणाम के बाद समूह को बेहतर बनाने के बाद यह बेहतर हो जाता है कि मैंगोडब इसे करने दें। – kappaallday