Как заменить подстроку в документе 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"}}])
-
filetranscoding -- Имя коллекции
-
profiles -- Имя столбца, в котором вы хотите обновить
-
/N_/ -- Строка, которую вы ищете (где Condition )
-
find:"N_",replacement: "" -- N_ который вы хотите удалить "" из которого вы хотите удалить здесь мы берем пустую строку