2012-04-06 19 views
23

में सभी दस्तावेज़ों में स्ट्रिंग को प्रतिस्थापित करने के लिए मुझे कुछ दस्तावेज़ों में एक स्ट्रिंग को प्रतिस्थापित करने की आवश्यकता है। मैंने इस कोड को गुगल किया है, लेकिन दुर्भाग्य से यह कुछ भी नहीं बदलता है। मैं लाइन bellow पर वाक्य रचना के बारे में निश्चित नहीं हूँ:मोंगो

pulpdb = db.getSisterDB("pulp_database"); 
var cursor = pulpdb.repos.find(); 
while (cursor.hasNext()) { 
    var x = cursor.next(); 
    x['source']['url'].replace('aaa', 'bbb'); // is this correct? 
    db.foo.update({_id : x._id}, x); 
} 

मैं कुछ डिबग प्रिंट जोड़ने के लिए देखने के लिए क्या मूल्य है चाहते हैं, लेकिन मैं MongoDB शेल के साथ कोई अनुभव। मैं तो बस इस प्रतिस्थापित करने की आवश्यकता:

{ "source": { "url": "http://aaa/xxx/yyy" } } 

साथ
{ "source": { "url": "http://bbb/xxx/yyy" } } 
+0

मोंगो खोल मनमाने ढंग से जावास्क्रिप्ट चलाता है जो बताता है कि आप कोड काम करते हैं। क्या आपने बस कोशिश की है? – Derick

उत्तर

37

यह आम तौर पर सही नहीं है: यदि आप स्ट्रिंग http://aaa/xxx/aaa (yyyaaa के बराबर है) आप http://bbb/xxx/bbb साथ पहुंच जाएंगे। लेकिन यदि आप इसके साथ ठीक हैं, तो कोड काम करेगा।

को जोड़ने के लिए डिबग जानकारी का उपयोग print समारोह:

var cursor = db.test.find(); 
while (cursor.hasNext()) { 
    var x = cursor.next(); 
    print("Before: "+x['source']['url']); 
    x['source']['url'] = x['source']['url'].replace('aaa', 'bbb'); 
    print("After: "+x['source']['url']); 
    db.test.update({_id : x._id}, x); 
} 

(और वैसे, अगर आप वस्तुओं बाहर प्रिंट करना चाहते हैं, वहाँ भी है printjson समारोह)

+0

ओह मैंने "प्रिंट" की कोशिश नहीं की :-) यह आसान है! ठीक है, मैं देख सकता हूं कि डेटा आ रहा है, मुझे लगता है कि मेरे पास regexp में एक झगड़ा है (वास्तविक मामला xxx नहीं है लेकिन https://abc.blablab.com) – lzap

+0

समझ गया - मुझे एक्स ['स्रोत करना पड़ा '] [' url '] = x [' स्रोत '] [' url ']। इसके बजाय (...) को प्रतिस्थापित करें। – lzap

+0

कुछ अजीब कारणों के लिए हम्म चर परिवर्तनीय है लेकिन डेटा तब संग्रहीत नहीं किया जाता है। क्या मुझे प्रतिबद्धता या कुछ करने की ज़रूरत है? मैं अभी भी पुराना डेटा देखता हूं। – lzap

1

MongoDB स्ट्रिंग खोज कर सकते हैं/मैप्रिडस के माध्यम से प्रतिस्थापित करें। हां, इसके लिए आपको एक बहुत ही विशेष डेटा संरचना की आवश्यकता है - आपके पास शीर्ष कुंजी में कुछ भी नहीं हो सकता है लेकिन आपको value के तहत सबडॉक्यूमेंट के तहत सब कुछ स्टोर करने की आवश्यकता है। इस तरह:

{ 
    "_id" : ObjectId("549dafb0a0d0ca4ed723e37f"), 
    "value" : { 
      "title" : "Top 'access denied' errors", 
      "parent" : "system.admin_reports", 
      "p" : "\u0001\u001a%" 
    } 
} 

बार जब आप इस बड़े करीने से की स्थापना की है आप कर सकते हैं:

$map = new \MongoCode("function() { 
    this.value['p'] = this.value['p'].replace('$from', '$to'); 
    emit(this._id, this.value); 
}"); 
$collection = $this->mongoCollection(); 
// This won't be called. 
$reduce = new \MongoCode("function() { }"); 
$collection_name = $collection->getName(); 
$collection->db->command([ 
    'mapreduce' => $collection_name, 
    'map' => $map, 
    'reduce' => $reduce, 
    'out' => ['merge' => $collection_name], 
    'query' => $query, 
    'sort' => ['_id' => 1], 
]); 
+0

यह समस्या का सही दृष्टिकोण नहीं है - mapReduce एक नया परिणाम सेट उत्पन्न कर सकता है, इसका उपयोग "प्रतिस्थापित करने के लिए नहीं किया जाना चाहिए "मौजूदा मूल्य इस तरह से। इसके अलावा आप कुछ विशिष्ट पर निर्भर हैं - इस संग्रह को अपने तरीके से प्रारूपित करने के लिए इस तरह प्रारूपित करने के लिए, मूल्य जोड़े जोड़े के दस्तावेजों पर पुनरावृत्ति करके इसे पहले से दिए गए उत्तर से अधिक जटिल लगता है। –

+0

शैल कमांड निष्पादित करने के लिए सभी वेब अनुप्रयोगों में विशेषाधिकार नहीं हैं। एक और दृष्टिकोण PHP में सभी को पुनर्प्राप्त करना, प्रतिस्थापित करना और वापस सहेजना होगा, लेकिन सर्वर में निश्चित रूप से तेज़ है। अंत में, क्या आप कुछ आधिकारिक दस्तावेज उद्धृत कर सकते हैं क्योंकि इसका उपयोग इस तरह क्यों नहीं किया जाना चाहिए? मैंने कुछ भी नहीं पढ़ा है कि आपको स्रोत में विलय नहीं करना चाहिए। – chx

+0

आप न तो मैपिंग और न ही कम कर रहे हैं :) असल में, आप ओवरराइटिंग कर रहे हैं और यह वास्तव में "मैप रेडस" का उद्देश्य नहीं है - आप सचमुच प्रत्येक दस्तावेज़ का अद्यतन कर रहे हैं। सबसे अच्छा, इसे एक हैक के रूप में वर्णित किया जा सकता है (जो केवल दस्तावेज़ के इस सटीक विशिष्ट प्रारूप पर काम करता है) –

1

सबसे अच्छा तरीका यह करने के लिए यदि आप MongoDB 2.6 या नए पर हैं का उपयोग कर कर्सर वस्तु पर पाशन है .forEach अधिकतम क्षमता के लिए प्रत्येक दस्तावेज़ usin "bulk" संचालन को विधि और अद्यतन करें।

var bulk = db.collection.initializeOrderedBulkOp(); 
var count = 0; 

db.collection.find().forEach(function(doc) { 
    print("Before: "+doc.source.url); 
    bulk.find({ '_id': doc._id }).update({ 
     '$set': { 'source.url': doc.source.url.replace('aaa', 'bbb') } 
    }) 
    count++; 
    if(count % 200 === 0) { 
     bulk.execute(); 
     bulk = db.collection.initializeOrderedBulkOp(); 
    } 

// Clean up queues 
if (count > 0) 
    bulk.execute(); 

MongoDB 3.2 से Bulk() एपीआई और उसके methods पदावनत कर रहे हैं आप db.collection.bulkWrite() विधि का उपयोग करने की आवश्यकता होगी जुड़े।

आपको कर्सर पर लूप की आवश्यकता होगी, अपनी क्वेरी गतिशील रूप से बनाएं और प्रत्येक ऑपरेशन को सरणी में $push बनाएं।

var operations = []; 
db.collection.find().forEach(function(doc) { 
    print("Before: "+doc.source.url); 
    var operation = { 
     updateOne: { 
      filter: { '_id': doc._id }, 
      update: { 
       '$set': { 'source.url': doc.source.url.replace('aaa', 'bbb') } 
      } 
     } 
    }; 
    operations.push(operation); 
}) 
operations.push({ 
    ordered: true, 
    writeConcern: { w: "majority", wtimeout: 5000 } 
}) 

db.collection.bulkWrite(operations); 
संबंधित मुद्दे