概要
RailsでMongoDBを使用する際、埋め込み型のリレーション(embeds_many)の子要素をピンポイントで変更する方法を記載します。
RailsでMongoDBを使うにあたって
MongoDBを使う際のORマッパーは、Mongoidを使用します。Mongoidのリレーションについては@kkyouheiさんのMongoのリレーションについてまとめてみたを参照ください。
サンプル例題
親要素はブログ記事、子要素はコメントとして、ブログ記事にコメントの配列を持たせるようなイメージになります。
article.rb
class Article
include Mongoid::Document
field :_id, type: String
field :title, type: String
field :contents, type: String
embeds_many :comments
end
comment.rb
class Comment
include Mongoid::Document
field :user_id, type: String
field :post_comment, type: String
embedded_in :article
end
対応方法
対象のドキュメントを親要素から全子要素を取得して置き換える方法も考えられますが、今回はMongoDBのクエリを発行できるMopedを使って、ドキュメントを取得せずにクエリ一発で変更する方法を紹介します。
実装サンプル
クエリ発行のためのコレクションの取得
sample.rb
db = Mongoid::Clients.default
# DB上で保存されるコレクションは親要素
articleCollection= db[:article]
追加
articleの_idを指定して、対象のarticleコレクションへcommentを追加する。
sample.rb
articleCollection.update_one(
{ "_id" => _id },
{ "$push" => {
"comments" => {
"user_id" => userId,
"post_comment" => postComment
}
}}
)
変更
artccleの_idと、commentのuser_idを指定して、commentを変更する。
sample.rb
articleCollection.update_one(
{ "_id" => _id, "comments.user_id" => userId },
{ "$set" => {
"comments.$.post_comment": postComment
}
}
)
削除
artccleの_idと、commentのuser_idを指定して、commentを削除する。
sample.rb
articleCollection.update_one(
{ "_id" => _id, "comments.user_id" => userId },
{ "$pull" => { "comments" => { "user_id" => userId } } }
)