Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

mongoid - querying embedded docs

class Foo
  include Mongoid::Document
  field :name, type: String
  embeds_many :bars
end

class Bar
  include Mongoid::Document
  field :name, type: String
  embedded_in :foo
end

Is there a way that I can query all of the bars here? In AR I'd do something like Bar.where(name: 'something') - just give me all the bars that match some criteria.

As it stands, I can only query the specific bars on a single foo. `Foo.first.bars.where(name: 'something'). I know mongoDB has no joins, so... I'm curious how to go about this.

I'm about ready to lose the Foo all together and do something like:

class Bar
  include Mongoid::Document
  field :foo_name, type: String
  field :name, type: String
end
like image 996
Dudo Avatar asked Jul 15 '14 03:07

Dudo


People also ask

How do I query embedded files in MongoDB?

Accessing embedded/nested documents – In MongoDB, you can access the fields of nested/embedded documents of the collection using dot notation and when you are using dot notation, then the field and the nested field must be inside the quotation marks.

How would you query an array of embedded documents in MongoDB?

Use the Array Index to Query for a Field in the Embedded Document. Using dot notation, you can specify query conditions for field in a document at a particular index or position of the array. The array uses zero-based indexing. When querying using dot notation, the field and index must be inside quotation marks.

What is embedded document in MongoDB?

MongoDB provides you a cool feature which is known as Embedded or Nested Document. Embedded document or nested documents are those types of documents which contain a document inside another document.

How do I query an array field in MongoDB?

To query if the array field contains at least one element with the specified value, use the filter { <field>: <value> } where <value> is the element value. To specify conditions on the elements in the array field, use query operators in the query filter document: { <array field>: { <operator1>: <value1>, ... } }


1 Answers

You are not able to return Bar object without first returning the Foo object it is embedded in.

You can query for a top level document (Foo) as matches for embedded documents.

foo = Foo.create(:name => 'foo1')
foo.bars << Bar.new(:name => 'bar1')

Foo.where(:'bars.name' => 'bar1').first
=> #<Foo _id: 53c4a380626e6f813d000000, name: "foo1">

Then once you have the Foos that match some embedded bar, you can find the bar you are looking for with another query (which just maps to an Array#find or Array#select

foo.bars << Bar.new(:name => 'bar2')
Foo.where(:'bars.name' => 'bar1').first.bars.where(:name => 'bar2').first
=> #<Bar _id: 53c4a380626e6f813d000001, name: "bar2">

Update: In cases where you are querying for the embedded document out of the parent document context, I recommend against the use of an embedded document. When you embed a document, you are saying "I do not intend for the document to exist on it's own". If you find yourself query for it directly then ditch the embedding. It is tempting to embed but typically you don't need/require it.

Note: I have de-embedded 100M+ entries and it was a long hectic process.

Note2: embedding some metadata or aggregate is an optimization best kept for times when you really need it

like image 152
nort Avatar answered Oct 17 '22 05:10

nort