最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Mongoose Populate with a condition - Stack Overflow

programmeradmin1浏览0评论

in a Node.js App with Mongoose(Mongodb), With this code i fetch users and their books:

Users.find({user_id: req.user.id}).populate('books').exec(..);

Right now i want to fetch users that has an special book. i do like this:

Users.find({user_id: req.user.id}).populate('books',null,{bookname:"harry potter"}).exec(..);

But it doesn't work. With this, my code fetches users with their books of null value and if that condition matches, return them instead of null. In fact most of my users has null value for books. but what i want is that if that condioton in populate section is not matches, do not return that user in result array at all!

What i have to do? i have to do another query or something on results for what i need?

in a Node.js App with Mongoose(Mongodb), With this code i fetch users and their books:

Users.find({user_id: req.user.id}).populate('books').exec(..);

Right now i want to fetch users that has an special book. i do like this:

Users.find({user_id: req.user.id}).populate('books',null,{bookname:"harry potter"}).exec(..);

But it doesn't work. With this, my code fetches users with their books of null value and if that condition matches, return them instead of null. In fact most of my users has null value for books. but what i want is that if that condioton in populate section is not matches, do not return that user in result array at all!

What i have to do? i have to do another query or something on results for what i need?

Share Improve this question asked Sep 6, 2015 at 13:44 FcoderFcoder 9,22618 gold badges68 silver badges103 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 3

All I can think here is that you are calling it wrong. You do not really show much context here other than that your .populate() parameters do not look correct.

Here is a correct listing as a reproducible example:

var async = require('async'),
    mongoose = require('mongoose'),
    Schema = mongoose.Schema;

var thingSchema = new Schema({
  _id: Number,
  name: String
},{ _id: false });

var parentSchema = new Schema({
  name: String,
  things: [{ type: Number, ref: 'Thing' }]
});

var Thing = mongoose.model( 'Thing', thingSchema ),
    Parent = mongoose.model( 'Parent', parentSchema );

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

var things = { "one": 1, "two": 2, "three": 3 };

async.series(
  [
    function(callback) {
      async.each([Thing,Parent],function(model,callback) {
        model.remove({},callback);
      },callback);
    },
    function(callback) {
      var parentObj = new Parent({ "name": "me" });
      async.each(
        Object.keys(things).map(function(key) {
          return { "name": key, "_id": things[key] }
        }),
        function(thing,callback) {
          var mything = new Thing(thing);
          parentObj.things.push(thing._id)
          mything.save(callback)
        },
        function(err) {
          if (err) callback(err);
          parentObj.save(callback);
        }
      );
    },
    function(callback) {
      console.log("filtered");
      var options = {
        path: 'things',
        match: { "name": { "$in": ['two','three'] } }
      };

      Parent.find().populate(options).exec(function(err,docs) {
        if (err) callback(err);
        console.log(docs);
        callback();
      });
    },
    function(callback) {
      console.log('unfiltered');
      Parent.find().populate('things').exec(function(err,docs) {
        if (err) callback(err);
        console.log(docs);
        callback();
      })
    }
  ],
  function(err) {
    if (err) throw err;
    mongoose.disconnect();
  }
);

Which will consistently give results like this:

filtered
[ { _id: 55ec4c79f30f550939227dfb,
    name: 'me',
    __v: 0,
    things:
     [ { _id: 2, name: 'two', __v: 0 },
       { _id: 3, name: 'three', __v: 0 } ] } ]
unfiltered
[ { _id: 55ec4c79f30f550939227dfb,
    name: 'me',
    __v: 0,
    things:
     [ { _id: 1, name: 'one', __v: 0 },
       { _id: 2, name: 'two', __v: 0 },
       { _id: 3, name: 'three', __v: 0 } ] } ]

So take a good look at your data and your calls. The .populate() call needs to match the "path" and then also provide a "match" to query the documents that are to be populated.

Use elemMatch:

var title = 'Harry Potter';
Users.find({books: {$elemMatch: {name: title}})
.exec(processResults);
发布评论

评论列表(0)

  1. 暂无评论