Модификаторы MongoDB/MongoMapper для встроенных документов
Нужна помощь в том, как использовать атомарные модификаторы во встроенном документе.
Для иллюстрации, давайте предположим, что у меня есть коллекция, которая выглядит следующим образом.
Коллекция сообщений
{
"_id" : ObjectId("blah"),
"title" : "Some title",
"comments" : [
{
"_id" : ObjectId("bleh"),
"text" : "Some comment text",
"score" : 0,
"voters" : []
}
]
}
Что я хочу сделать с MongoMapper/MongoDB, так это выполнить атомарное обновление определенного комментария в почтовом документе.
Что-то вроде:
class Comment
include MongoMapper::EmbeddedDocument
# Other stuff...
# For the current comment that doesn't have the current user voting, increment the vote score and add that user to the voters array so they can't vote again
def upvote!(user_id)
collection.update({"comments._id" => post_id, "comments.voters" => {"$ne" => user_id}},
{"$inc" => {"comments.score" => 1}, "$push" => {"comments.voters" => user_id}})
end
end
Это в основном то, что у меня сейчас, и это не работает вообще (ничего не обновляется). В идеале, я бы также хотел перезагрузить документ / внедренный документ, но кажется, что не может быть способа сделать это, используя встроенный документ MongoMapper. Есть идеи, что я делаю не так?
1 ответ
Решение
Получил это работает для всех, кто заинтересован. Две вещи, которые мне не хватало
- С помощью
$elemMatch
искать объекты в массиве, которые должны удовлетворять двум условиям (например, _id = "" И избиратели НЕ содержат user_id) - С использованием
$
оператор на$inc
а также$push
операции, чтобы убедиться, что я изменяю конкретный объект, на который ссылается мой запрос.
def upvote!(user_id)
# Use the Ruby Mongo driver to make a direct call to collection.update
collection.update(
{
'meanings' => {
'$elemMatch' => {
'_id' => self.id,
'voters' => {'$ne' => user_id}
}
}
},
{
'$inc' => { 'meanings.$.votes' => 1 },
'$push' => { 'meanings.$.voters' => user_id }
})
end