programing

Mongo의 모든 문서에서 문자열을 바꾸는 방법

css3 2023. 6. 24. 09:26

Mongo의 모든 문서에서 문자열을 바꾸는 방법

특정 문서의 문자열을 교체해야 합니다.이 코드를 구글에 검색했지만 아쉽게도 변경되지 않았습니다.아래 행의 구문에 대해 잘 모르겠습니다.

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" } }

일반적으로 수정되지 않습니다. 문자열이 있는 경우http://aaa/xxx/aaa(yyy와 동등한.aaa)로 끝나게 될 것입니다.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함수)

MongoDB 2.6 이상 버전에 있는 경우 가장 좋은 방법은 메서드를 사용하여 커서 오브젝트를 루프하고 "대량" 작업으로 각 문서를 업데이트하여 효율성을 극대화하는 것입니다.

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 및 관련 메서드가 더 이상 사용되지 않습니다. 이 메서드를 사용해야 합니다.

커서를 루프하여 쿼리를 동적으로 빌드하고 각 작업을 배열로 만들어야 합니다.

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

요즘 들어,

  • 시작하는Mongo 4.2(db.collection.updateMany대신)db.collection.update)에서 집계 파이프라인을 허용할 수 있으며, 마지막으로 자체 값을 기준으로 필드를 업데이트할 수 있습니다.
  • 시작하는Mongo 4.4새로운 집계 연산자를 사용하면 문자열의 일부를 매우 쉽게 바꿀 수 있습니다.
// { "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")
  • 두 번째 부분($set: { "source.url": {...)는 업데이트 집계 파이프라인입니다(집계 파이프라인 사용을 나타내는 대괄호 참조).
    • $set 는 새로운 집계 연산자(Mongo 4.2이 경우 필드 값을 대체합니다.
    • 새 값은 새 연산자를 사용하여 계산됩니다.방법에 주목source.url자체 값을 기준으로 직접 수정됩니다($source.url).

이것은 질문의 디버그 인쇄 부분을 수행할 수 없는 완전히 처리된 서버 측입니다.

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],
]);

언급URL : https://stackoverflow.com/questions/10042450/how-to-replace-string-in-all-documents-in-mongo