27

特定のドキュメントの文字列を置き換える必要があります。このコードをグーグルで検索しましたが、残念ながら何も変わりません。次の行の構文についてはよくわかりません。

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 Shell の経験がありません。これを置き換えるだけです:

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

{ "source": { "url": "http://bbb/xxx/yyy" } }
4

4 に答える 4

38

It doesn't correct generally: if you have string http://aaa/xxx/aaa (yyy equals to aaa) you'll end up with http://bbb/xxx/bbb. But if you ok with this, code will work.

To add debug info use print function:

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

(And by the way, if you want to print out objects, there is also printjson function)

于 2012-04-06T11:00:08.553 に答える
4

MongoDB 2.6 以降を使用している場合にこれを行う最善の方法は、メソッドを使用してカーソル オブジェクトをループし、最大の効率を得るために「一括」.forEach操作を使用して各ドキュメントを更新することです。

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() API とそれに関連するメソッドは廃止され、メソッドを使用する必要があります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);
于 2015-11-08T08:01:07.430 に答える
2

現在、

  • 開始Mongo 4.2, db.collection.updateMany(のエイリアスdb.collection.update) は集計パイプラインを受け入れることができ、最終的には独自の値に基づいてフィールドを更新できます。
  • を開始するMongo 4.4と、新しい集計演算子$replaceOneにより、文字列の一部を簡単に置き換えることができます。
// { "source" : { "url" : "http://aaa/xxx/yyy" } }
// { "source" : { "url" : "http://eee/xxx/yyy" } }
db.collection.updateMany(
  { "source.url": { $regex: /aaa/ } },
  [{
    $set: { "source.url": {
      $replaceOne: { input: "$source.url", find: "aaa", replacement: "bbb" }
    }}
  }]
)
// { "source" : { "url" : "http://bbb/xxx/yyy" } }
// { "source" : { "url" : "http://eee/xxx/yyy" } }
  • 最初の部分 ( ) は、更新するドキュメント ( を含むドキュメント){ "source.url": { $regex: /aaa/ } }をフィルタリングする一致クエリです。"aaa"
  • 2 番目の部分 ( $set: { "source.url": {...) は、更新集計パイプラインです (集計パイプラインの使用を示す角括弧に注意してください)。
    • $setMongo 4.2この場合、フィールドの値を置き換える新しい集計演算子 ( ) です。
    • 新しい値は new$replaceOne演算子で計算されます。source.url独自の値 ( ) に基づいて直接変更される方法に注意してください$source.url

これは完全にサーバー側で処理されるため、質問のデバッグ印刷部分を実行できないことに注意してください。

于 2020-02-22T11:26:57.187 に答える
1

MongoDB は、mapreduce を介して文字列の検索/置換を行うことができます。はい、それには非常に特別なデータ構造が必要です。トップキーには何も入れることはできませんが、サブドキュメントの下にすべてを保存する必要があります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],
]);
于 2014-12-26T19:47:37.170 に答える