Как заменить подстроку в документе mongodb

У меня есть много документов mongodb в коллекции ABC вида:

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

Я хочу заменить helloWorldt на окончательный вывод helloWorld:

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

Как мне добиться этого для всех документов в коллекции ABC

13 ответов

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

Начало Mongo 4.2, db.collection.update() может принять конвейер агрегации, наконец, разрешив обновление поля на основе другого поля:

// { URL: "www.abc.com/helloWorldt/..." }
// { URL: "www.abc.com/HelloWo/..." }
db.collection.update(
  { URL: { $regex: "/helloWorldt/" } },
  [{
    $set: { URL: {
      $concat: [
        { $arrayElemAt: [ { $split: [ "$URL", "/helloWorldt/" ] }, 0 ] },
        "/helloWorld/",
        { $arrayElemAt: [ { $split: [ "$URL", "/helloWorldt/" ] }, 1 ] }
      ]
    }}
  }],
  { multi: true }
)
// { URL: "www.abc.com/helloWorld/..." }
// { URL: "www.abc.com/HelloWo/..." }

Это немного многословно, так как нет правильной строки $replace Оператор еще.

  • Первая часть { URL: { $regex: "/helloWorldt/" } } является запросом на совпадение, фильтрующим, какие документы обновлять (с ошибочно написанным Привет, мир).

  • Вторая часть [{ $set: { URL: ... } }] является конвейером агрегации обновлений (обратите внимание на квадратные скобки, обозначающие использование конвейера агрегации). $set это новый оператор агрегирования, который в этом случае создает / заменяет поле. Новое значение странным образом вычисляется с использованием смеси $concat а также $split из-за отсутствия правильной строки $replace оператор. Обратите внимание, как URL изменяется напрямую на основе собственной стоимости ($URL).

  • Не забывай { multi: true } иначе будет обновлен только первый соответствующий документ.

Использование mongodump,bsondump и mongoimport.

Иногда коллекции mongodb могут быть немного сложными с вложенными массивами / объектами и т. Д., Где было бы относительно сложно построить циклы вокруг них. Мой обходной путь довольно сырой, но работает в большинстве сценариев, независимо от сложности коллекции.

1. Экспортируйте коллекцию с помощью mongodump в.bson

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

2. Конвертировать.bson в формат.json, используя bsondump

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

3. Замените строки в файле.json на sed(для терминала linux) или любыми другими инструментами.

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

4. Импортируйте коллекцию.json с помощью mongoimport с тегом --drop, где он будет удалять коллекцию перед импортом.

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

В качестве альтернативы вы можете использовать --uri для соединений в mongoimport и mongodump

пример

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/

В настоящее время вы не можете использовать значение поля для его обновления. Поэтому вам придется перебирать документы и обновлять каждый документ с помощью функции. Вот пример того, как вы можете сделать это здесь: MongoDB: Обновление документов с использованием данных из того же документа

Чтобы заменить ВСЕ вхождения подстроки в вашем документе, используйте:

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

nodejs. Использование пакета mongodb из 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});
  });
});

Форматирование моего комментария к выбранному ответу (ответ @Naveed) зашифровано - поэтому добавьте его в качестве ответа. Весь кредит идет на Навид.

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

Просто потрясающе. Мой случай был - у меня есть поле, которое является массивом - поэтому мне пришлось добавить дополнительный цикл.

Мой запрос:

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

Если вы хотите найти подстроку и заменить ее другой, вы можете попробовать, как показано ниже,

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

Это можно сделать с помощью Regex в первой части метода replace и он заменит [все, если g в шаблоне регулярного выражения] вхождения (я) этой строки со второй строкой, это то же регулярное выражение, что и в Javascript, например:

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

Поскольку регулярное выражение заменяет строку, теперь мы можем сделать это с помощью оболочки MongoDB легко, найдя и перебирая каждый элемент методом forEach и сохраняя один за другим внутри forEach цикл, как показано ниже:

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

Теперь вы можете сделать это!

Мы можем использовать скрипт Mongo для управления данными на лету. Меня устраивает!

Я использую этот скрипт для исправления моих адресных данных.

Пример текущего адреса: "№12, ПЯТЫЙ ПРОСПЕКТ,".

Я хочу удалить последнюю лишнюю запятую, ожидаемый новый адрес "№ 12, ПЯТЫЙ ПРОСПЕКТ".

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

  }
}

Надеюсь это поможет!

На всякий случай, если вы используете примеры из ответов здесь и получаете "Обновлено 0 существующих записей" при запуске сценария замены, проверьте, подключен ли ваш клиент к основному узлу MongoDB, который позволяет вам сохранять / записывать изменения.

Вы можете попробовать ниже конвейер агрегации в 3.4 версия.

Запрос агрегации для замены строки поиска строкой замены.

Логика заключается в том, чтобы найти строку поиска ($indexOfCP) с последующим $concat объединить все части ($substrCP), часть перед соответствующей строкой поиска, замещающей строкой и остальной исходной строкой.

Массовое обновление, чтобы написать новую структуру URL.

var bulk = db.getCollection(col).initializeUnorderedBulkOp();
var count = 0;
var batch = 1;

db.getCollection(col).aggregate([
  {"$project":{
    "URL":{
      "$let":{
        "vars":{
          "len":{
            "$strLenCP":"helloWorldt"},"start":{"$indexOfCP":["$URL","helloWorldt"]}
        },
        "in":{
          "$concat":[
            {"$substrCP":["$URL",0,"$$start"]},
            "helloWorld",
            {"$substrCP":[
              "$URL",
              {"$add":["$$start","$$len"]},
              {"$subtract":[{"$strLenCP":"$URL"},{"$add":["$$start","$$len"]}]}
            ]}
          ]
        }
      }
    }
  }}
]).forEach(function(doc){ 
    var _id = doc._id; 
    var url = doc.URL; 
    bulk.find({ "_id" : _id }).updateOne(
        { $set: {"URL" : url } }
    ); 
    count++;  
    if (count == batch) { 
      bulk.execute(); 
      bulk = db.getCollection(col).initializeUnorderedBulkOp(); 
      count = 0;
    } 
});

 if (count > 0) { 
    bulk.execute(); 
 }

db.filetranscoding.updateMany({ профили: {$regex: /N_/} },[{$set: {профили: {$$replaceAll: {ввод: "$profiles", найти:"N_",замена: "" }},"статус":"100"}}])

  1. filetranscoding -- Имя коллекции

  2. profiles -- Имя столбца, в котором вы хотите обновить

  3. /N_/ -- Строка, которую вы ищете (где Condition )

  4. find:"N_",replacement: "" -- N_ который вы хотите удалить "" из которого вы хотите удалить здесь мы берем пустую строку

Другие вопросы по тегам