2016-08-20 5 views
5

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

मुझे $ प्रकार चयनकर्ता के साथ भी समस्याएं आ रही हैं क्योंकि यह अलग-अलग सरणी तत्वों के प्रकार प्रकार को लागू कर रहा है, जो तार हैं। तो प्रकार के अनुसार फ़िल्टरिंग सब कुछ देता है।

मैं दूसरे दस्तावेज़ के प्रारूप में पहले उदाहरण की तरह दिखने वाले प्रत्येक दस्तावेज़ को कैसे प्राप्त कर सकता हूं?

{ 
    "_id" : ObjectId("12345"), 
    "tags" : "red blue green white" 
} 
{ 
    "_id" : ObjectId("54321"), 
    "tags" : [ 
     "red", 
     "orange", 
     "black" 
    ] 
} 
+0

उत्कृष्ट प्रश्न .. मैंने कोशिश की लेकिन इसे मोंगोडब में हल करने में सक्षम नहीं था .. फिर मैंने मोंगोड जीरा पर देखा और इसके काम में प्रगति हुई .. https://jira.mongodb.org/browse/SERVER-6773 – user641887

+0

@ user641887 कि जिरा पहले ही बंद है।लेकिन मोंगो डीबी में '$ split' के बिना ऐसा करना संभव है। एकमात्र समस्या प्रदर्शन है। – styvane

उत्तर

2

हम $type ऑपरेटर यहाँ हमारे दस्तावेजों फिल्टर करने के लिए उपयोग नहीं कर सकते क्योंकि हमारे सरणी में तत्वों के प्रकार "स्ट्रिंग" है और के रूप में दस्तावेज में उल्लेख किया है:

सरणियों पर लागू किए जाने , $ प्रकार किसी भी आंतरिक तत्व से मेल खाता है जो निर्दिष्ट बीएसओएन प्रकार का है। उदाहरण के लिए, जब $ प्रकार: 'सरणी' के लिए मिलान करते हैं, तो फ़ील्ड से मेल खाएगा यदि फ़ील्ड में नेस्टेड सरणी है। यह परिणाम वापस नहीं करेगा जहां फ़ील्ड स्वयं एक सरणी है।

लेकिन सौभाग्य से मोंगोडीबी $exists ऑपरेटर भी प्रदान करता है जिसका उपयोग यहां एक संख्यात्मक सरणी अनुक्रमणिका के साथ किया जा सकता है।

अब हम उन दस्तावेजों को कैसे अपडेट कर सकते हैं?

ठीक है, मोंगोडीबी संस्करण < = 3.2 से, हमारे पास एकमात्र विकल्प mapReduce() है लेकिन पहले मोंगोडीबी की आगामी रिलीज में अन्य विकल्प को देखने दें।

मोंगोडीबी 3.4 से शुरू होकर, हम $project हमारे दस्तावेज़ों को $split ऑपरेटर का उपयोग कर सकते हैं ताकि हमारी स्ट्रिंग को सबस्ट्रिंग्स की सरणी में विभाजित किया जा सके।

ध्यान दें कि स्ट्रिंग वाले केवल "टैग" को विभाजित करने के लिए, हमें स्ट्रिंग वाले मानों को विभाजित करने के लिए लॉजिकल $cond इयनियन प्रोसेसिंग की आवश्यकता है। यहां की स्थिति $eq है जो true का मूल्यांकन करती है जब फ़ील्ड के $type"string" के बराबर है। वैसे $type यहां 3.4 में नया है।

अंत में हम $out पाइपलाइन चरण ऑपरेटर का उपयोग करके पुराने संग्रह को ओवरराइट कर सकते हैं। लेकिन हमें $project चरण में अन्य फ़ील्ड को शामिल करने की स्पष्ट रूप से निर्दिष्ट करने की आवश्यकता है।

db.collection.aggregate(
    [ 
     { "$project": { 
      "tags": { 
       "$cond": [ 
        { "$eq": [ 
         { "$type": "$tags" }, 
         "string" 
        ]}, 
        { "$split": [ "$tags", " " ] }, 
        "$tags" 
       ] 
      } 
     }}, 
     { "$out": "collection" } 
    ] 
) 

mapReduce के साथ, हम Array.prototype.split() उपयोग करने के लिए हमारे नक्शा समारोह में सबस्ट्रिंग सरणी फेंकना की जरूरत है। हमें "क्वेरी" विकल्प का उपयोग करके हमारे दस्तावेज़ों को फ़िल्टर करने की भी आवश्यकता है। वहां से हम "टैग" 3.2 में bulkWrite() विधि नए का उपयोग करके बल्क संचालन प्रयोग करने के लिए "परिणाम" सरणी और $set नया मान या पुनरावृति करने की आवश्यकता होगी अब Bulk() पदावनत अगर हम 2.6 पर हैं या 3.0 दिखाया गया है here.

db.collection.mapReduce(
    function() { emit(this._id, this.tags.split(" ")); }, 
    function(key, value) {}, 
    { 
     "out": { "inline": 1 }, 
     "query": { 
      "tags.0": { "$exists": false }, 
      "tags": { "$type": 2 } 
     } 
    } 
)['results'] 
संबंधित मुद्दे