MongoDB - использование $ in с $ pull для обновления влияет только на одну запись вместо всех указанных в $ in - PullRequest
3 голосов
/ 07 марта 2012

Хорошо, это может быть немного сложно визуализировать без публикации примера рассматриваемой спецификации документа, но я не уверен, что это даже уместно в этом случае.

По сути, то, что я пытаюсь сделать здесь, это $pull выделение определенной части документа из списка идентификаторов записей. Вот пример (мы используем PyMongo для взаимодействия с базой данных):

distinct_poster_ids = self._db.activities.find({"_id": activity_id}).distinct("feed.poster_id")

if distinct_poster_ids:
  document = {
    "$pull": {
      "feed": {
        "_id": activity_id,
        "object": "activity"
      }
    }
  }

  self._db.posters.update({"_id": {"$in": distinct_poster_ids}}, document, multi=True)

То, что я пытаюсь сделать здесь, это удалить «активность» из каналов «постеров», которые участвовали в указанной «деятельности». Итак, я извлекаю идентификаторы всех «постеров» из «действия», а затем использую этот список в предложении $in оператора update. Затем я пытаюсь $pull выделить соответствующие части поддокумента "Постеры".

Проблема здесь в том, что он применяет это изменение только к первому элементу в списке или к первому «постеру». Насколько я знаю, синтаксис правильный, но это может быть крайний случай.

Я могу лениво пройтись по списку и применить этот оператор к каждому идентификатору в отдельности, но Я бы предпочел разгрузить его в БД, если он его поддерживает.

Как всегда, большое спасибо!

Edit:

Установите Mongod на максимальную степень детализации -vvvvvv и извлекайте следующую запись из журналов, которые соответствуют вызову PyMongo:

update posters query: { _id: { $in: [ "1", "10", "18537", "19778", "20137", "20967", "4", "54", "5835", "9" ] } } update: { $pull: { feed: { _id: "4020800", object: "activity" } } }

Затем я вошел в оболочку и выполнил обновление вручную:

db.posters.update({ _id: { $in: [ "1", "10", "18537", "19778", "20137", "20967", "4", "54", "5835", "9" ] } }, { $pull: { feed: { _id: "4020800", object: "activity" } } })

Я проверил поврежденные записи в оболочке, и она отлично работала. Я думаю, что это может быть крайний случай или ограничение в привязках PyMongo. Во всяком случае, если кто-то может пролить свет на это, я был бы очень рад!

1 Ответ

2 голосов
/ 07 марта 2012

При обновлении нескольких документов в одной команде обновления необходимо установить для мультифлага значение true. Как показано в вашем примере с pymongo, он уже имеет значение true. Но журнал, который вы извлекли, не показывает никаких признаков мульти флага. Я считаю, что это проблема.

Посмотрите на приведенный ниже пример, выполненный в оболочке Монго с мульти

> db.posters.insert({_id:1,feed:[{_id:"4020800", object: "activity"}]})
> db.posters.insert({_id:10,feed:[{_id:"4020800", object: "activity"}]})
> db.posters.insert({_id:101,feed:[{_id:"4020800", object: "activity"}]})
> db.posters.find()
{ "_id" : 1, "feed" : [ { "_id" : "4020800", "object" : "activity" } ] }
{ "_id" : 10, "feed" : [ { "_id" : "4020800", "object" : "activity" } ] }
{ "_id" : 101, "feed" : [ { "_id" : "4020800", "object" : "activity" } ] }

и

> db.posters.update({ _id: { $in: [ 1, 10]}}, { $pull: { feed: { _id: "4020800", object: "activity" } } },false,true)
> db.posters.find()
{ "_id" : 1, "feed" : [ ] }
{ "_id" : 10, "feed" : [ ] }
{ "_id" : 101, "feed" : [ { "_id" : "4020800", "object" : "activity" } ] }

Работает нормально. Поэтому я считаю, что проблема в драйвере, а не в монго.

Кроме того, я не верю, что в вашем последнем примере это тоже хорошо работает

Затем я вошел в оболочку и выполнил обновление вручную:

db.posters.update({ _id: { $in: [ "1", "10", "18537", "19778", "20137", "20967", "4", "54", "5835", "9" ] } }, { $pull: { feed: {

_id: "4020800", объект: "активность"}}})

Я проверил поврежденные записи в оболочке, и это сработало идеально.

Без мульти-флага обновляется только первый элемент. ниже образца

> db.posters.update({ _id: { $in: [ 1, 10]}}, { $pull: { feed: { _id: "4020800", object: "activity" } } })
> db.posters.find()
{ "_id" : 1, "feed" : [ ] }
{ "_id" : 10, "feed" : [ { "_id" : "4020800", "object" : "activity" } ] }
{ "_id" : 101, "feed" : [ { "_id" : "4020800", "object" : "activity" } ] }
...