0

I'm trying to get the intersection of two queries on some embedded docuements using Mongoid 3.

So (fake example) imagine I have:

class Post
  embeds_many :comments

  index 'comments.author_id' => 1
end

class Comments
  embedded_in :post
  belongs_to :author
end

If I wanted to get posts with a comment from a user I could just do

Post.where(:'comments.author_id' => User.first.id)

But what if I want to get posts that have comments by both of these users:

u1 = User.first.id
u2 = User.last.id
Post.where(:'comments.author_id' => u1.id, :'comments.author_id' => u2.id)

This doesn't work in mongoid 3. It overwrites the first comments.author_id with the second so you get something like this:

command={:count=>"posts", :query=>{"comments.author_id"=>"505d1eb5f8182b7082000017"}}

Other variations I've tried without any luck:

Post.where(:'comments.author_id' => u1.id).where(:'comments.author_id' => u2.id)
Post.where(:'comments.author_id' => u1.id).and.where(:'comments.author_id' => u2.id)
Post.where(:'comments.author_id' => u1.id).intersect.where(:'comments.author_id' => u2.id)
Post.all_of(:'comments.author_id' => u1.id, :'comments.author_id' => u2.id)

Is there a better way to construct this query? Thanks!

Brian Armstrong
  • 19,707
  • 17
  • 115
  • 144

1 Answers1

1

The issue here is that by the example Mongoid doesn't get a chance to do anything with it, since you've provided a Ruby hash where before the method is executed it gets evaluated to having only 1 key in it (since the keys are the same):

Post.where(:'comments.author_id' => u1.id, :'comments.author_id' => u2.id)

What you want to do is:

Post.any_in(:'comments.author_id' => [ u1.id, u2.id ])

modetojoy
  • 166
  • 1
  • Oh yes, can't believe I didn't think of this! Thanks for the answer. Related question: Would it be possible to get posts with a comment from 1 author but *not* from the other? Sort of like a `:'comments.author_id'.ne => u2.id` on the second one? – Brian Armstrong Sep 24 '12 at 18:29