Подтвердить что ты не робот

Mongodb: upserting: только установить значение, если документ вставлен

Учитывая простую структуру документа mongo:

{_id, firstTime, lastTime}

Клиенту необходимо вставить документ с известным идентификатором или обновить существующий документ. "LastTime" всегда должен быть установлен в последнее время. Для "firstTime" , если документ вставлен, тогда "firstTime" следует установить на текущее время. Однако, если документ уже создан, то "firstTime" остается неизменным. Я хотел бы сделать это исключительно с помощью upserts (чтобы избежать поисковых запросов).

Я просканировал http://www.mongodb.org/display/DOCS/Updating, но я просто не вижу, как эта конкретная операция может быть выполнена.

Я не считаю, что это что-то необоснованное, есть операции $push и $addToSet, которые эффективно делают это в полях массива, просто ничего, что могло бы сделать то же самое на простых полях. Это похоже на что-то вроде операции $setIf.

4b9b3361

Ответ 1

Я столкнулся с одной и той же проблемой и не было простого решения для < 2.4, однако, поскольку 2.4 оператор $setOnInsert позволяет делать именно это.

db.collection.update( <query>,
                      { $setOnInsert: { "firstTime": <TIMESTAMP> } },
                      { upsert: true }
                    )

Для получения дополнительной информации см. примечания к выпуску версии setOnInsert.

Ответ 2

Нет никакого способа сделать это с помощью только одного upsert. Вам нужно будет сделать это как 2 операции - сначала попробуйте вставить документ, если он уже существует, вставка не удастся из-за дублирования нарушения ключа в индексе _id. Затем вы выполните операцию обновления, чтобы установить lastTime.

Ответ 3

У меня возникла очень похожая проблема при попытке обновить документы на основе существующего контента - возможно, это решение также сработает для вас:

Попробуйте удалить атрибут _id из своей записи и использовать его только в части запроса вашего обновления (вам нужно будет перевести с pymongo говорить...)

myid = doc.get('_id')
del doc['_id']
mycollection.update({'_id':myid}, {'$set':doc}, upsert=True)