2012-04-06 5 views
23

特定の文書の文字列を置き換える必要があります。私はこのコードをgoogled、しかしそれは残念ながら何も変更されません。私はライン怒鳴る上の構文について確認していない:Mongoのすべての文書でstringを置き換える方法

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://bbb/xxx/yyy" } } 
+0

Mongoシェルは、youreコードが動作することを示唆する任意のjavascriptを実行します。あなたは単にそれを試したことがありますか? – Derick

答えて

37

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

:あなたは文字列http://aaa/xxx/aaaを(yyyaaaに等しい)がある場合は、http://bbb/xxx/bbbになってしまいます私はこれを交換する必要があります。 これで問題なければ、コードは機能します。

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

ああ、私は "プリント"しようとしなかった:-)それは簡単!さて、私はデータが入って来るのを見ることができます、私は正規表現の中で(本当のケースはxxxではなくhttps://abc.blablab.com) – lzap

+0

を持っていると思います - 私はx ['source '] [' url '] = x [' source '] [' url ']。代わりに(...)を置き換えてください。 – lzap

+0

奇妙な理由から、変数は置き換えられますが、データは格納されません。私はコミットや何かを実行する必要がありますか?私はまだそこに古いデータを見ています。 – lzap

1

のMongoDBは、文字列検索を行うことができます。print機能を使用するデバッグ情報を追加するには

/mapreduce経由で置き換えます。はい、あなたはそれのための非常に特殊なデータ構造を持っている必要があります - あなたはトップキーに何もすることはできませんが、valueの下にすべてのサブ文書の下に格納する必要があります。このように:あなたはこのきちんと設定したら

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

あなたが行うことができます:あなたはMongoDBの2.6またはそれ以降である場合は、これを行うには

$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は新しい結果セットを生成することができます。 "既存の値をこのようにします。さらに、非常に具体的な何かに依存しています - あなたのコレクションをこのようにフォーマットして_idを出力するだけで、値のペアは、シェル内のドキュメントを反復処理することにより、すでに与えられた答えより複雑に思えます。 –

+0

すべてのWebアプリケーションがシェルコマンドを実行する特権を持っているわけではありません。もう1つのアプローチは、すべてをPHPに取り込み、置き換えて保存することですが、サーバーでは確実に高速です。最後に、なぜこのように使用すべきではないとの公式文書を引用することができますか?私はあなたがソースにマージしてはならないと言っていることは何も読んでいない。 – chx

+0

あなたはマッピングも縮小もしていません:)基本的には、上書きしています。それは実際には「mapReduce」の目的ではありません。文字通り各ドキュメントの更新を行っています。せいぜい、これはハックとして記述することができます(これは文書のこの特定の形式でのみ動作します) –

1

最善の方法を使用してカーソルオブジェクトをループさ.forEachメソッドを使用して、効率を最大化するために各ドキュメントを"bulk"操作で更新してください。 MongoDB 3.2から

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(); 

Bulk() APIと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); 
関連する問題