Mongoid criteria for referenced relations
I have these 2 models:
class Track
include Mongoid::Document
field :artist, type: String
field :title, type: String
field :isrc, type: String
has_many :subtitles
end
class Subtitle
include Mongoid::Document
field :lines, type: Array
belongs_to :track
end
How can I check if a track exi开发者_如何学Csts that has a certain 'isrc' and has subtitles (no matter how many)?
I've been trying this but it seems to ignore the subtitles criteria:
Track.exists?(conditions: {isrc: my_isrc, :subtitles.exists => true})
It returns true even if the track with that 'isrc' has no subtitles. what to do?
You simply cannot do this way in mongo, since Track & subtitle stored in different documents. Exists command in mongodb only can verify the fields in its own documents, here the relationship is maintained in Subtitle document as track_id not in Track document. So Track doesn't have the track of subtitles.
One easy way to achieve this is to change your relation from belongs_to to embedded. So Track can easily verify the subtitles using $exists.
Another way is
Track.where(:isrc => my_isrc).select {|track| track.subtitles.count > 0}
But disadvantage in this query is multiple round trips made to mongo to verify each tracks subtitle count.
For anyone else struggling with this, I found that mapping the ids to a list, and then using the any_in or all_in functions does the trick.
I needed to get all the messages sent to a user, but messages aren't related directly to my users. Instead, users belong to lists, and lists have many messages. To get messages that "belong to" a user, I did this:
Here's my controller:
@lists = @group.lists.where(deleted: false).order_by([:created_at, :desc])
@messages = Messages.any_in(list: @lists.map(&:id))
@messages = @messages.order_by([:created_at, :desc]).paginate(:page => params[:page], :per_page => 3)
The Messages.any_in(list: @lists.map(&:id)) was the key insight.
精彩评论