Как сделать upsert / push с монгоидом / мопедом

Я использую Mongoid (v3) для доступа к MongoDB и хочу выполнить это действие:

db.sessionlogs.update( 
    {sessionid: '12345'}, /* selection criteria */
    {'$push':{rows: "new set of data"}},  /* modification */
    true /* upsert */
);

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

Как я могу получить MongoID с пути и просто отправить эту команду в MongoDB? Я предполагаю, что есть какой-то способ сделать это на уровне мопедов, но документации этой библиотеки в основном не существует.

3 ответа

Решение

[Ответ найден при написании вопроса...]

criteria = Sessionlogs.collection.find(:sessionid => sessionid)
criteria.upsert("$push" => {"rows" => datarow})

Вот один из способов сделать это:

session_log = SessionLog.new (session_id: '12345')
session_log.upsert
session_log.push (: строки, "новый набор данных")

Или другой:

SessionLog.find_or_create_by (session_id: '12345').
  push (: строки, "новый набор данных")

#push выполняет атомную $push на поле. Это объясняется на странице " Атомная стойкость".

(Примечание: в примерах используются UpperCamelCase и snake_case, как это принято в Ruby.)

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

Пример сохранения ребра на графике, если он не существует

edge = {source_id: session[:user_id],dest_id:product._id, name: edge_name}
ProductEdge.where(edge).find_and_modify(ProductEdge.new(edge).as_document,{upsert:true})
Другие вопросы по тегам