开发者

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜