So ersetzen Sie Teilzeichenfolgen in Mongodb-Dokumenten


74

Ich habe viele Mongodb-Dokumente in einer Sammlung des Formulars:

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

Ich möchte ersetzen helloWorldtdurch helloWorld:

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

Wie kann ich dies für alle Dokumente in meiner Sammlung erreichen?

Antworten:


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

2
Kannst du es bitte näher erläutern? Wie funktioniert es? Was ist der Mittelwert des Codes? auch für andere Benutzer?
Aman

3
Einfach super. Mein Fall war - ich habe ein Feld, das ein Array ist - also musste ich eine zusätzliche Schleife hinzufügen. Meine Frage ist:db.getCollection("profile").find({"photos": {$ne: "" }}).forEach(function(e,i) { e.photos.forEach(function(url, j) { url = url.replace("http://a.com", "https://dev.a.com"); e.photos[j] = url; }); db.getCollection("profile").save(e); eval(printjson(e)); })
Himel Nag Rana

3
@doe "e" steht hier für eine Kopie jedes gefundenen Dokuments. Der Wert dieser Kopie für die URL (Groß- und Kleinschreibung wird beachtet, beachten Sie, dass dies nicht mit der "URL" des Fragestellers identisch ist) wurde basierend auf dem ursprünglichen Wert für die URL aktualisiert. "e" behält alle ursprünglichen Felder mit dem einen geänderten Feld bei. Wenn Sie e wieder in der Sammlung speichern, wird das ursprüngliche "e" überschrieben. Hier ist "i" nicht erforderlich und es kann aus der Funktionsdeklaration entfernt werden.
JMess

bitte auch für andere benutzer erklären ??
Pirai Sudie

Sicherlich wäre es möglich, nur das eine Feld zu aktualisieren, das sich geändert hat, anstatt das gesamte Dokument zu lesen und zurückzuschreiben.
Arthur Tacca

29

Heutzutage,

  • beginnend Mongo 4.2, db.collection.updateMany(alias der db.collection.updatebasierend auf seinen eigenen Wert) kann eine Aggregations Pipeline schließlich nehmen die Aktualisierung eines Feldes ermöglicht.
  • Ab Mongo 4.4sofort $replaceOnemacht es der neue Aggregationsoperator sehr einfach, einen Teil einer Zeichenfolge zu ersetzen.
// { 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/..." }
  • Der erste Teil ( { URL: { $regex: /helloWorldt/ } }) ist die Übereinstimmungsabfrage, bei der gefiltert wird, welche Dokumente aktualisiert werden sollen (welche enthalten "helloWorldt"), und die nur dazu dient, die Abfrage zu beschleunigen.
  • Der zweite Teil ( $set: { URL: {...) ist die Aktualisierungsaggregationspipeline (beachten Sie die eckigen Klammern, die die Verwendung einer Aggregationspipeline angeben):
    • $setist ein neuer Aggregationsoperator ( Mongo 4.2), der in diesem Fall den Wert eines Feldes ersetzt.
    • Der neue Wert wird mit dem neuen $replaceOneOperator berechnet . Beachten Sie, wie URLdirekt basierend auf dem eigenen Wert ( $URL) geändert wird .

Vor Mongo 4.4und nach dem Start Mongo 4.2müssen $replacewir aufgrund des Fehlens eines geeigneten String- Operators eine Bancal-Mischung aus $concatund $split:

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

Danke, kann es mit Regex in verwendet werden find?
3.

Danke, sind die Schrägstriche ("/") beim Ersatz erforderlich?
dhalfageme

@dhalfageme Ich sehe Verwirrung im letzteren Beispiel. Die Schrägstriche nach dem $regexOperator (dh $regex: "/helloWorldt/") sind Trennzeichen für reguläre Ausdrücke, die erforderlich sind. An allen anderen Stellen im Beispiel sind die Schrägstriche URL-Pfadbegrenzer und wahrscheinlich nicht erforderlich. Sie wären nur notwendig, wenn das OP URLs mit einem Pfad hätte, der / helloWorldthirsty / enthält, den sie behalten wollten.
David Siegal


5

nodejs. Verwendung des Mongodb-Pakets ab npm

db.collection('ABC').find({url: /helloWorldt/}).toArray((err, docs) => {
  docs.forEach(doc => {
    let URL = doc.URL.replace('helloWorldt', 'helloWorld');
    db.collection('ABC').updateOne({_id: doc._id}, {URL});
  });
});

5

Verwenden Sie Folgendes, um ALLE Vorkommen der Teilzeichenfolge in Ihrem Dokument zu ersetzen :

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

3
Die Vars müssen nicht in der Schleife sein, also setzen Sie sie vorher.
Paul

Die Vars sollten const sein.
Mirko

4

Die Formatierung meines Kommentars auf die ausgewählte Antwort (@ Naveeds Antwort) wurde verschlüsselt - fügen Sie dies also als Antwort hinzu. Alle Kredite gehen an Naveed.

-------------------------------------------------- --------------------

Einfach super. Mein Fall war - ich habe ein Feld, das ein Array ist - also musste ich eine zusätzliche Schleife hinzufügen.

Meine Anfrage lautet:

db.getCollection("profile").find({"photos": {$ne: "" }}).forEach(function(e,i) {
    e.photos.forEach(function(url, j) {
        url = url.replace("http://a.com", "https://dev.a.com");
        e.photos[j] = url;
    });
    db.getCollection("profile").save(e);
    eval(printjson(e));
})

4

Mit Mongodump, Bsondump und Mongoimport.

Manchmal können die Mongodb-Sammlungen mit verschachtelten Arrays / Objekten usw. wenig komplex werden, wobei es relativ schwierig wäre, Schleifen um sie herum zu erstellen. Meine Arbeit ist etwas roh, funktioniert aber in den meisten Szenarien, unabhängig von der Komplexität der Sammlung.

1. Exportieren Sie die Sammlung mit Mongodump in .bson

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

2. Konvertieren Sie .bson mit bsondump in das .json-Format

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

3. Ersetzen Sie die Zeichenfolgen in der .json-Datei durch sed (für Linux-Terminal) oder durch andere Tools

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

4. Importieren Sie die .json-Sammlung mit mongoimport mit dem Tag --drop zurück, wo die Sammlung vor dem Import entfernt wird

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

Alternativ können Sie --uri für Verbindungen sowohl im Mongoimport als auch im Mongodump verwenden

Beispiel

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/

1

Jetzt kannst du es schaffen!

Wir können das Mongo-Skript verwenden, um Daten im laufenden Betrieb zu bearbeiten. Für mich geht das!

Ich benutze dieses Skript, um meine Adressdaten zu korrigieren.

Beispiel für die aktuelle Adresse: "No.12, FIFTH AVENUE,".

Ich möchte das letzte redundante Komma entfernen, die erwartete neue Adresse "" Nr. 12, FIFTH AVENUE ".

var cursor = db.myCollection.find().limit(100);

while (cursor.hasNext()) {
  var currentDocument = cursor.next();

  var address = currentDocument['address'];
  var lastPosition = address.length - 1;

  var lastChar = address.charAt(lastPosition);

  if (lastChar == ",") {

    var newAddress = address.slice(0, lastPosition);


    currentDocument['address'] = newAddress;

    db.localbizs.update({_id: currentDocument._id}, currentDocument);

  }
}

Hoffe das hilft!


1

Dies kann mithilfe von Regexim ersten Teil der Methode erfolgen replaceund ersetzt die gVorkommen dieser Zeichenfolge durch die zweite Zeichenfolge. Dies ist derselbe reguläre Ausdruck wie in Javascript, z.

const string = "www.abc.com/helloWorldt/...";
console.log(string);
var pattern = new RegExp(/helloWorldt/)
replacedString = string.replace(pattern, "helloWorld");
console.log(replacedString);

Da der reguläre Ausdruck die Zeichenfolge ersetzt, können wir dies jetzt problemlos in der MongoDB-Shell tun, indem wir jedes Element nach der Methode suchen und iterieren forEachund nacheinander in der forEachSchleife wie folgt speichern :

> db.media.find()
{ "_id" : ObjectId("5e016628a16075c5bd26fbe3"), "URL" : "www.abc.com/helloWorld/" }
{ "_id" : ObjectId("5e016701a16075c5bd26fbe4"), "URL" : "www.abc.com/helloWorldt/" }
> 
> db.media.find().forEach(function(o) {o.URL = o.URL.replace(/helloWorldt/, "helloWorld"); printjson(o);db.media.save(o)})
{
    "_id" : ObjectId("5e016628a16075c5bd26fbe3"),
    "URL" : "www.abc.com/helloWorld/"
}
{
    "_id" : ObjectId("5e016701a16075c5bd26fbe4"),
    "URL" : "www.abc.com/helloWorld/"
}
> db.media.find()
{ "_id" : ObjectId("5e016628a16075c5bd26fbe3"), "URL" : "www.abc.com/helloWorld/" }
{ "_id" : ObjectId("5e016701a16075c5bd26fbe4"), "URL" : "www.abc.com/helloWorld/" }
>

0

Nur für den Fall, dass Sie Beispiele aus den Antworten hier verwenden und beim Ausführen Ihres Ersetzungsskripts "0 vorhandene Datensätze aktualisiert" erhalten, prüfen Sie, ob Ihr Client mit dem primären MongoDB-Knoten verbunden ist, über den Sie Änderungen speichern / schreiben können.


0

Wenn Sie nach einer Unterzeichenfolge suchen und diese durch eine andere ersetzen möchten, können Sie Folgendes versuchen:

    db.collection.find({ "fieldName": /.*stringToBeReplaced.*/ }).forEach(function(e, i){
        if (e.fieldName.indexOf('stringToBeReplaced') > -1) {
          e.content = e.content.replace('stringToBeReplaced', 'newString');
          db.collection.update({ "_id": e._id }, { '$set': { 'fieldName': e.fieldName} }, false, true);
        }
    }) 
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.