118 votes

Comment remplacer une sous-chaîne dans un document mongodb ?

J'ai beaucoup de documents mongodb dans une collection de la forme :

{
....
"URL":"www.abc.com/helloWorldt/..."
.....
}

Je veux remplacer helloWorldt con helloWorld pour obtenir :

{
....
"URL":"www.abc.com/helloWorld/..."
.....
}

Comment puis-je réaliser cela pour tous les documents de ma collection ?

155voto

Naveed Points 1781
db.media.find({mediaContainer:"ContainerS3"}).forEach(function(e,i) {
    e.url=e.url.replace("//a.n.com","//b.n.com");
    db.media.save(e);
});

106voto

Xavier Guihot Points 6414

De nos jours,

  • démarrage Mongo 4.2 , db.collection.updateMany (alias de db.collection.update ) peut accepter un pipeline d'agrégation, permettant finalement la mise à jour d'un champ sur la base de sa propre valeur.

  • démarrage Mongo 4.4 le nouvel opérateur d'agrégation $replaceOne permet de remplacer très facilement une partie d'une chaîne de caractères.

    // { URL: "www.abc.com/helloWorldt/..." } // { URL: "www.abc.com/HelloWo/..." } db.collection.updateMany( { URL: { $regex: /helloWorldt/ } }, [{ $set: { URL: { $replaceOne: { input: "$URL", find: "helloWorldt", replacement: "helloWorld" } }} }] ) // { URL: "www.abc.com/helloWorld/..." } // { URL: "www.abc.com/HelloWo/..." }

  • La première partie ( { URL: { $regex: /helloWorldt/ } } ) est la requête de correspondance, filtrant les documents à mettre à jour (ceux contenant "helloWorldt" ) et est juste là pour rendre la requête plus rapide.

  • La deuxième partie ( $set: { URL: {... ) est le pipeline d'agrégation des mises à jour (notez les crochets qui indiquent l'utilisation d'un pipeline d'agrégation) :

    • $set est un nouvel opérateur d'agrégation ( Mongo 4.2 ) qui, dans ce cas, remplace la valeur d'un champ.
    • La nouvelle valeur est calculée avec la nouvelle $replaceOne opérateur. Notez comment URL est modifié directement sur la base de sa propre valeur ( $URL ).

Avant Mongo 4.4 et en commençant Mongo 4.2 en raison de l'absence d'une chaîne de caractères appropriée $replace opérateur, nous devons utiliser un mélange bancal de $concat y $split :

db.collection.updateMany(
  { URL: { $regex: "/helloWorldt/" } },
  [{
    $set: { URL: {
      $concat: [
        { $arrayElemAt: [ { $split: [ "$URL", "/helloWorldt/" ] }, 0 ] },
        "/helloWorld/",
        { $arrayElemAt: [ { $split: [ "$URL", "/helloWorldt/" ] }, 1 ] }
      ]
    }}
  }]
)

9voto

Ry Van Points 60

Utilisation de mongodump, bsondump et mongoimport.

Parfois, les collections mongodb peuvent devenir un peu complexes avec des tableaux/objets imbriqués, etc. où il serait relativement difficile de construire des boucles autour d'eux. Ma méthode de travail est un peu rudimentaire mais fonctionne dans la plupart des cas, quelle que soit la complexité de la collection.

1. Exporter la collection en utilisant mongodump en .bson

mongodump --db=<db_name> --collection=<products> --out=data/

2. Convertir le format .bson en .json à l'aide de bsondump

bsondump --outFile products.json data/<db_name>/products.bson

3. Remplacez les chaînes de caractères dans le fichier .json avec sed(pour le terminal linux) ou avec tout autre outil.

sed -i 's/oldstring/newstring/g' products.json

4. Importez à nouveau la collection .json avec mongoimport avec la balise --drop qui supprimera la collection avant l'importation.

mongoimport --db=<db_name>  --drop --collection products <products.json

Alternativement, vous pouvez utiliser --uri pour les connexions dans les deux mongoimport et mongodump

exemple

mongodump --uri "mongodb://mongoadmin:mystrongpassword@10.148.0.7:27017,10.148.0.8:27017,10.148.0.9:27017/my-dbs?replicaSet=rs0&authSource=admin" --collection=products --out=data/

8voto

Louisa Points 841

Actuellement, vous ne pouvez pas utiliser la valeur d'un champ pour le mettre à jour. Vous devez donc itérer dans les documents et mettre à jour chaque document à l'aide d'une fonction. Vous trouverez ici un exemple de la façon dont vous pouvez procéder : MongoDB : mise à jour de documents à l'aide de données provenant du même document

6voto

Pour remplacer TOUTES occurrences de la sous-chaîne dans votre document utiliser :

db.media.find({mediaContainer:"ContainerS3"}).forEach(function(e,i) {
var find = "//a.n.com";
var re = new RegExp(find, 'g');
e.url=e.url.replace(re,"//b.n.com");
db.media.save(e);
});

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X