Замените элементы в поле массива в mongodb во всех записях

#mongodb #mongodb-query #replaceall

Вопрос:

 {
    "_id": ObjectId("60743bd0ffb98b1e7c215c1b"),
    "orderId": "787968",
    "notes":"Leave in porch"
    "lineItems": [
        {
            "lineItemId": "1741547",
            "channelLineItemId": "9741370294381",
            "skuId": "XXX-YYY-x-PR-YYY"
        },
        {
            "lineItemId": "1741549",
            "channelLineItemId": "9741370359917",
            "skuId": "XXX-YYY-x-PR-YYY"
        },
        {
            "lineItemId": "1741551",
            "channelLineItemId": "9741370425453",
            "skuId": "XXX-YYY-x-P-YYY"
        }
    ],
    "Data": {
        "email_status": "SENT",
        "sent_date": ISODate("2021-04-12T12:23:48.623Z")
    }
}
 

У меня в моем монго была коллекция данных о порядке с вышеуказанной структурой.

Мне нужно заменить все -PR- и -PG- простым дефисом - во всех записях и во всех элементах строк. т. е. ему нужно перебрать все записи и все элементы массива. если я использую команду SQL, я буду использовать

update line_item set sku_id = replace(sku_id , '-PR-','-');

после выполнения команды XYZ-BCD-X-PR-ZAB будет XYZ-BCD-X-AB

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

 db.orderData.find().forEach(function(doc) {
    doc.note : doc.note.replace('-PG-', '-');
    db.orderData.save(doc);
});

 

Я не знаю, как использовать то же самое при обновлении в массиве

Я пытался

 db.orderData.find({orderId : "787968"}).forEach(function(doc) {
    doc.lineItems.$.skuId : doc.lineItems.$.skuId.replace('-PG-', '-');
    db.orderData.save(doc);
});
 

но это не работает.

Кто-нибудь, пожалуйста, помогите мне и заранее спасибо.

Комментарии:

1. в каких областях вы хотите это сделать? только в skuId ?

Ответ №1:

Вы можете сделать это, поместив конвейер агрегации в update :

  1. использовать $addFields в $map lineItems массиве;
  2. используйте $replaceAll $map для замены-PR — на
  3. повторите шаг 2 для замены-PG — на * на другом $addFields этапе

Вот игровая площадка Монго для вашей справки.


Обновление как OP с использованием Mongo DB 3.6

Поскольку $replaceAll доступно только начиная с Mongo DB 4.4, $replaceAll его можно было бы заменить приведенным ниже обходным решением:

  1. $split по -PR- или -PG- разбить на массив сегментов
  2. присоединитесь к массиву $reduce и {$concat: ["$$value","-","$$this"]}
  3. В этом случае в поле будут введены 2 дополнительных дефиса $concat . Используйте $substrCP , чтобы вырезать 2 дефиса заголовка.

Вот игровая площадка Монго для вашей справки.

Комментарии:

1. он может стать меньше с картой за 1 доллар, я думаю так

2. Спасибо @Takis_, это хорошая мысль. Я думаю, что ОП должен использовать вашу краткую версию в своем реальном коде. Я бы просто сохранил свою немного утомительную версию для демонстрационных целей здесь.

3. мой монго-версия 3.6, я думаю, что функция replaceAll недоступна в этой версии. есть ли какая-либо функция, которая может поддерживать эту версию 3.6

4. Я обновил ответ альтернативой, используя $split , $concat , $reduce , $strLenCP , которая должна быть доступна в MongoDB 3.6