Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Searching Embedded Objects in Mongoose

For example if I have the following Schema (greatly simplified for brevity). How can I search for posts by Tag? I know how to do this if the tag document collection was embedded but I want to keep Tag's in their own collection.

PostSchema = new Schema({
    title: String
    body: String
    tags: [{type: Schema.ObjectId, ref: 'Tag' }]
});

TagSchema = new Schema({
    name: String
});

// Here is what I've tried
Post.find({'tags.name':'javascript'})
    .populate('tags') // Is it necessary to join the collections?
    .run(function(err, posts) {
       console.log('posts: ', posts);
    });
like image 253
Eric Clifford Avatar asked Dec 05 '11 18:12

Eric Clifford


2 Answers

You should be able to use the object.field notation with mongoose to query embedded docs. However, you might need to make sure your embedded doc has all the fields declared as part of the schema in order (in your sample, you query on "comments.name" but PostSchema has no comments field - maybe this is causing the problem?)

I was able to get a proof of concept working like this, which should run successfully as-is:

var mongoose = require('mongoose')
var Schema = mongoose.Schema

mongoose.connect('mongodb://localhost/testjs');


PostSchema = new Schema({
  title: String,
  body: String,
  comments: [],
  tags: [{type: Schema.ObjectId, ref: 'Tag' }]
});

TagSchema = new Schema({
  name: String
});


var Post = mongoose.model('Post', PostSchema);

var mypost = new Post()
mypost.title = "yo"
mypost.body = "asfkjabfkjbsdf"
mypost.comments = [{'name':'javascript', 'text':'sup'}]
mypost.save(
  function(err){
    // Save the post, and then read it back by querying the embedded field
    Post.find({'comments.name':'javascript'},function(err, posts){
      console.log('posts: ', posts);
    });
  }
);
like image 135
mpobrien Avatar answered Sep 21 '22 02:09

mpobrien


Is having a Schema for tags the best approach? Something simpler like this should work:

Posts = new Schema({
    title: String
    body: String
    tags: [String]
})

// ...

Posts.find({ tags: { $in: ['javascript'] }, function(err, posts){
    console.log(posts)
})
like image 25
Ricardo Tomasi Avatar answered Sep 21 '22 02:09

Ricardo Tomasi