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