Is it possible to perform a query and return the embedded documents?
Currently, I have:
class Post
include MongoMapper::Document
many :comments
end
class Comment
include MongoMapper::EmbeddedDocument
belongs_to :post
key :author
key :date
key :body
end
Here is a query that is almost there:
Post.all("comments.date" => {"$gt" => 3.days.ago})
This will return all the post objects but not the comments. I guess I could do something like:
Post.all("comments.date" => {"$gt" => 3.days.ago}).map(&:comments)
But this would return all comments from the posts. I'd like to get all of the comments that met this condition. Perhaps Comment
should not be embedded.
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.
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.
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.
Match an Embedded/Nested Document To specify an equality condition on a field that is an embedded/nested document, use the query filter document { <field>: <value> } where <value> is the document to match.
I assume you're looking for all comments newer than three days ago? Since your Comments are just embedded documents, they do not exist without the Post object so there's no way to "query" them separately (this is actually a future feature of MongoDB). However, you could easily add a convenience method to help you out:
class Comment
include MongoMapper::EmbeddedDocument
def self.latest
Post.all(:conditions => {"comments.date" => {"$gt" => 3.days.ago}}).map{|p| p.comments}.flatten
end
end
This method would get you all of the comments that have been updated in the last three days but they would not entirely be in order. A better solution might be to use Map/Reduce to pull the latest comments:
class Comment
include MongoMapper::EmbeddedDocument
def self.latest
map = <<-JS
function(){
this.comments.forEach(function(comment) {
emit(comment.created_at, comment)
});
}
JS
r = "function(k,vals){return 1;}"
q = {'comments.created_at' => {'$gt' => 3.days.ago}}
Post.collection.map_reduce(m,r,:query => q).sort([['$natural',-1]])
end
end
Caveat: the above is completely untested code and just exists as an example, but theoretically should return all comments from the last three days sorted in descending order.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With