Comment remplacer la chaîne de caractères dans tous les documents de Mongo

j'ai besoin de remplacer une chaîne dans certains documents. J'ai googlé ce code, mais il ne change malheureusement rien. Je ne suis pas sûr de la syntaxe sur la ligne ci-dessous:

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

j'aimerais ajouter quelques tirages de débogage pour voir quelle est la valeur, mais je n'ai pas d'expérience avec MongoDB Shell. J'ai juste besoin de remplacer ceci:

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

{ "source": { "url": "http://bbb/xxx/yyy" } }
23
demandé sur styvane 2012-04-06 14:48:55

3 réponses

il n'est pas correct en général: si vous avez string http://aaa/xxx/aaa (yyy est égal à aaa), vous vous retrouverez avec http://bbb/xxx/bbb. Mais si vous êtes d'accord avec ça, le code marchera.

Pour ajouter les informations de débogage utiliser print fonction:

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

(Et en passant, si vous voulez imprimer des objets, il y a aussi printjson function)

37
répondu om-nom-nom 2012-04-06 11:22:25

MongoDB peut faire la recherche de chaîne / remplacer via mapreduce. Oui, vous devez avoir une structure de données très spéciale pour cela -- vous ne pouvez rien avoir dans les touches du haut mais vous devez tout stocker sous un sous-document sous value. Comme ceci:

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

une fois que vous avez ce bien configuré vous pouvez faire:

$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],
]);
1
répondu chx 2014-12-26 19:47:37

la meilleure façon de le faire si vous êtes sur MongoDB 2.6 ou plus récent est de faire une boucle sur l'objet curseur en utilisant le .forEach méthode et mise à jour chaque document usin "en vrac" opérations pour une efficacité maximale.

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.2en Vrac() API et de ses associés méthode sont obsolètes, vous devrez utiliser le db.collection.bulkWrite() méthode.

Vous aurez besoin de boucle sur le curseur, construisez votre requête dynamiquement et $push chaque opération à un tableau.

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);
1
répondu styvane 2015-11-08 08:01:07