Upsert с $in

Мне нужны следующие функции в MongoDB. У меня есть коллекция с именем «сущности», которая в основном хранит текст сущности и ее количество. Коллекция выглядит так:

[{u'_id': u'facebook', u'n': 120},
 {u'_id': u'florida', u'n': 98},
 {u'_id': u'vegas', u'n': 94},
 {u'_id': u'andrew_mason', u'n': 93},
 {u'_id': u'obama', u'n': 85},
 {u'_id': u'twitter', u'n': 81},
 {u'_id': u'outlook', u'n': 81},
 {u'_id': u'delhi', u'n': 75},
 {u'_id': u'google', u'n': 74},
 {u'_id': u'virginia', u'n': 71}]

Теперь я хочу обновить эту коллекцию новыми сущностями. По сути, у меня будут новые объекты, готовые в массиве, например:

entitySet = ['google', 'Abhishek_Vaid', 'andrew_mason']

Мои намерения заключаются в том, что для сущностей, уже находящихся в коллекции, их количество должно быть обновлено. Что касается объектов, не в коллекции, их количество должно быть инициализировано равным 1. Я хочу использовать один запрос MongoDB для достижения обоих этих эффектов. До сих пор я мог найти следующий запрос: (Это вариант PyMongo, но, тем не менее, это запрос MongoDB)

ENTITY_DB_HANDLE.entities.update (

{'_id' : {'$in' : entitySet} }, {'$inc' : {'n' : 1} }, upsert=True, multi=True )

Однако этот запрос только обновляет количество существующих сущностей и не отправляет новые сущности.

Любые идеи по этому поводу?


person VaidAbhishek    schedule 04.03.2013    source источник


Ответы (1)


Конечно работает:

> db.test.save({_id:"a", n:3})
> db.test.update({_id:"b"}, {$inc:{n:1}}, true, false)
> db.test.find()
{ "_id" : "a", "n" : 3 }
{ "_id" : "b", "n" : 1 }

Но в вашем примере запроса не используется $in, поэтому я предполагаю, что вы действительно пытаетесь:

{'_id' : {$in:['google', 'Abhishek_Vaid', 'andrew_mason']}, {'$inc' : {'n' : 1} }, upsert=True, multi=True )

и ожидайте, что он обновит или создаст запись для каждого переданного вами значения _id. Это не будет работать, если какое-либо из значений _id уже существует, поскольку upsert создаст только новый документ, если документ не соответствует критериям поиска.

person Remon van Vliet    schedule 04.03.2013
comment
Да, моя ошибка. Я обновил вопрос. Пожалуйста, еще раз посмотрите. Но я не понял вашего ответа. - person VaidAbhishek; 04.03.2013
comment
@VaidAbhishek Уже сделал это во второй половине моего ответа;) Это никогда не сработает, потому что upsert работает иначе. Чтобы сделать то, что вы хотите сделать, вам придется перебирать уникальные идентификаторы и вызывать обновление upsert=true для каждого из них. - person Remon van Vliet; 04.03.2013
comment
Спасибо за ваше время. Да, я надеялся избежать этого. Тем не менее, я до сих пор не уверен, почему это не работает. Потому что upsert=True явно означает, что для каждого обработанного документа (через совпадение _id), если документ не существует, я намереваюсь вставить его. Я имею в виду, что если это не сработает, то я могу не предоставлять опцию upsert и иметь дело только с multi=True. Тогда какая польза от опции upsert в первую очередь? - person VaidAbhishek; 04.03.2013
comment
Не знаете, какое поведение вы ожидаете здесь, не могли бы вы уточнить, что именно вы хотели бы, чтобы он делал? Как упомянул Ремон, обновление вставит новый документ, если не найдет соответствия запросу. - person ACE; 05.03.2013
comment
@VaidAbhishek Вариант использования upsert следующий: он создаст новый документ, если и только если НИ ОДИН из документов в коллекции не соответствует вашим критериям поиска. Ваш запрос на основе $in соответствует одному или нескольким документам и, следовательно, не приведет к созданию нового документа. В основном вы можете думать об этом так; upsert создаст не более одного документа. По вашему мнению, это потенциально может создать до X документов, где X — это количество значений идентификатора в вашем $in. - person Remon van Vliet; 05.03.2013
comment
Я надеялся на что-то, что могло бы вставить X отсутствующих документов за один вызов - вместо того, чтобы совершать обход для каждого элемента в массиве - может быть, в какой-то будущей версии... - person Nic Cottrell; 05.03.2014
comment
Боюсь, нет, и обратите внимание, что на самом деле это очень сложная функция для реализации. - person Remon van Vliet; 24.03.2014