Как я могу обновить или вставить вложенные документы в массив в mongdb - PullRequest
1 голос
/ 11 января 2020

Я довольно новичок в mongodb, так что вот мой вопрос: я хочу проверить, существует ли основной документ, а затем, если он есть, проверить, существует ли вложенный документ, обновить его и не вставлять новый , Но с помощью этого кода я могу только обновить существующий вложенный документ, но не могу создать новый. Я даже не знаю, правильно ли это использовать этот метод, это эффективно?

collection.find_one_and_update(
 {"_id:{"field1":val1,"field2":val2,"field3":val3,"field4":val4}},
 {"$set":{"elements.$[element].prop2":valToUpdate}},
 return_document=ReturnDocument.AFTER, 
 array_filters=[{"element.prop1":valToCheck}],
 upsert=True
)

В синтаксисе mon go я думаю, что-то вроде этого:

db.collection.findOneAndUpdate(
   {"_id:{"field1":val1,"field2":val2,"field3":val3,"field4":val4}},
   {"$set":{"elements.$[element].prop2":valToUpdate}},
   { arrayFilters: [ {"element.prop1":valToCheck} ] }
)

Могу ли я использовать одну такую ​​функцию для выполнения всего процесса (проверьте, является ли основной и вложенный документ существует, и если он обновляется, в противном случае создайте новый)?

Пример того, как я хочу изменить документ:

перед выполнением метода

{
   "_id":{"name":"Storename","location":"somewhere","phone":46284723},
   "books":
      [
         {"name":"somebook","price":{"$numberDouble":"34"}}
      ]
}

После выполнения, если есть вложенный документ

{
   "_id":{"name":"Storename","location":"somewhere","phone":46284723},
   "books":
      [
         {"name":"somebook","price":{"$numberDouble":"55"}},
      ]
}

После выполнения, если нет вложенного документа

{
   "_id":{"name":"Storename","location":"somewhere","phone":46284723},
   "books":
      [
         {"name":"somebook","price":{"$numberDouble":"34"}},

         {"name":"someOTHERbook","price":{"$numberDouble":"45"}}
      ]
}

1 Ответ

1 голос
/ 11 января 2020

Это потому, что upsert, похоже, не работает вместе с оператором $, также в общем случае upsert находится на уровне документа, но не должен использоваться для вставки отсутствующих элементов массива, как в этом сценарии. Поскольку фактический документ существует в БД, он будет через ошибку дубликата _id.

. Если вы хотите сделать это в одном вызове БД, тогда приведенный ниже запрос должен работать для вашего сценария, как и в любом конкретном случае. только один updateOne должен обновить массив:

Пн go Запрос:

db.yourCollectionName.bulkWrite([
    {
        updateOne: {
            filter: {
                "_id": {
                    "name": "Storename",
                    "location": "somewhere",
                    "phone": 46284723
                }, 'books.name': 'somebook'
            }, update: {
                $set: { "books.$.price": 100 }
            }
        }
    },
    {
        updateOne: {
            filter: {
                "_id": {
                    "name": "Storename",
                    "location": "somewhere",
                    "phone": 46284723,
                }
            }, update: {
                $addToSet: { 'books': { 'name': 'somebook', "price": 100 } }
            }
       }
 }])

Python Код:

import pymongo
from pymongo import UpdateOne

bulkArr = [
    UpdateOne({
        "_id": {
            "name": "Storename",
            "location": "somewhere",
            "phone": 46284723
        }, 'books.name': 'somebook'
    }, { '$set': { "books.$.price": 100 } }),
    UpdateOne({
        "_id": {
            "name": "Storename",
            "location": "somewhere",
            "phone": 46284723,
        }
    }, {
        $addToSet: { 'books': { 'name': 'somebook', "price": 100 } }
       })
   ]

db.yourCollectionName.bulk_write(bulkArr)

PyMon go Ref: Пожалуйста, используйте эту ссылку, чтобы преобразовать этот запрос. PyMon go -bulk_write

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...