67

只是一个简单的查询,例如模型中有一个双引用。

架构/模型

var OrderSchema = new Schema({

    user: {
        type    : Schema.Types.ObjectId,
        ref     : 'User',
        required: true
    },

    meal: {
        type    : Schema.Types.ObjectId,
        ref     : 'Meal',
        required: true
    },
});

var OrderModel = db.model('Order', OrderSchema);

询问

OrderModel.find()
    .populate('user') // works
    .populate('meal') // dont works
    .exec(function (err, results) {
         // callback
    });

我已经尝试过类似的东西

.populate('user meal')
.populate(['user', 'meal'])

事实上,只有一个人口有效。

那么,如何让两个人口工作?

4

11 回答 11

86

您已经在使用正确的语法:

OrderModel.find()
    .populate('user')
    .populate('meal')
    .exec(function (err, results) {
         // callback
    });

也许meal订单中的 ObjectId 不在Meals集合中?

于 2012-10-10T15:15:37.360 回答
38

更新:
此解决方案仍然适用于 Mongoose 的 3.x 版本
http://mongoosejs.com/docs/3.8.x/docs/populate.html
但不再记录 >= 4.x 版本的 Mongoose 等答案来自@JohnnyHK 是目前唯一有效的。

原始帖子
如果您使用的是 Mongoose >= 3.6,您可以传递路径名称的空格分隔字符串来填充:

OrderModel.find()
    .populate('user meal')
    .exec(function (err, results) {
         // callback
    });

http://mongoosejs.com/docs/populate.html

于 2015-09-09T07:49:04.240 回答
16

这可能已经解决了,但这是我对 Mongodb > 3.6 中多重和深度人口的看法:

OrderModel.find().populate([{
    path: 'user',
    model: 'User'
}, {
    path: 'meal',
    model: 'Meal'
}]).exec(function(err, order) {
    if(err) throw err;
    if(order) {
        // execute on order
        console.log(order.user.username); // prints user's username
        console.log(order.meal.value);    // you get the idea
    }
});

可能还有其他方法可以做到这一点,但这为初学者(如我)提供了非常易读的代码

于 2018-05-11T23:44:23.873 回答
12

我认为最好的解决方案是当您在同一级别上填充多个外国字段时使用数组。我的代码显示我有多个不同级别的填充。

const patients = await Patient.find({})
                    .populate([{
                        path: 'files',
                        populate: {
                            path: 'authorizations',
                            model: 'Authorization'
                        },
                        populate: {
                            path: 'claims',
                            model: 'Claim',
                            options: {
                                sort: { startDate: 1 }
                            }
                        }
                    }, {
                        path: 'policies',
                        model: 'Policy',
                        populate: {
                            path: 'vobs',
                            populate: [{
                                path: 'benefits'
                            }, {
                                path: 'eligibility', 
                                model: 'Eligibility'
                            }]
                        }
                    }]);

如您所见,只要我需要填充文档的多个字段,我将填充键封装在一个数组中并提供一组对象,每个对象都有不同的路径。在我看来,最强大和简洁的方式来做到这一点。

于 2020-03-09T01:26:06.180 回答
5

你可以试试:

OrderModel.find()
    .populate('user')
    .populate('meal')
    .exec(function (err, results) {
         // callback
    });

或使用数组选项

OrderModel.find()
    .populate([
      {
        path: "path1",
        select: "field",
        model: Model1
      },
      {
        path: "path2",
        select: "field2",
        model: Model2
      }
    ])
    .exec(function (err, results) {
         // callback
    });
于 2020-03-08T15:15:23.373 回答
5

最新的 mongoosev5.9.15 具有获取填充字段数组的能力,因此您可以这样做,

.populate([ 'field1', 'field2' ])
于 2020-05-19T08:08:12.120 回答
3

您可以使用array语法:

let results = await OrderModel.find().populate(['user', 'meal']);

您还可以从每个填充中选择所需的属性:

let results = await OrderModel.find().populate([{path: 'user', select: 'firstname'}, {path: 'meal', select: 'name'}]);
于 2021-10-24T22:48:22.703 回答
0

我有同样的问题,但我的错误不是填充,我的模型有错误

如果你这样做

未校正

user: {
 type: [Schema.Types.ObjectId],
 ref: 'User'
} 

正确的

user: [{
 type: Schema.Types.ObjectId,
 ref: 'User'
}]

你必须像这样在对象周围放置数组

于 2019-06-12T23:44:36.463 回答
0

为了在控制器/动作函数中使用对象数组填充多个字段,两者的模型已经在 post 的模式中引用

post.find({}).populate('user').populate('comments').exec(function (err,posts)
    {
    
    if(err)
    {
        console.log("error in post");
    }
    
        return  res.render('home',{
            h1:"home Page",
            posts:posts,
            
            });      
        });
于 2020-11-19T08:57:06.607 回答
0

我认为您正在尝试嵌套人口,您可以访问官方文档

User.
  findOne({ name: 'Val' }).
  populate({
    path: 'friends',
    // Get friends of friends - populate the 'friends' array for every friend
    populate: { path: 'friends' }
  });
于 2021-08-21T10:17:08.850 回答
0

在模型文件中执行以下操作:-

 doctorid:{
        type:Schema.Types.ObjectId, ref:'doctor'
        },
    clinicid:{
        type:Schema.Types.ObjectId, ref:'baseClinic'
        }

在用于添加运算符的 js 文件中使用类似的东西:-

 const clinicObj = await BaseClinic.findOne({clinicId:req.body.clinicid})
 const doctorObj = await Doctor.findOne({ doctorId : req.body.doctorid}) ;
**and add data as:-**
const newOperator = new Operator({
      clinicid:clinicObj._id,
      doctorid: doctorObj._id
    });

现在,在填充

apiRoutes.post("/operator-by-id", async (req, res) => {
    const id = req.body.id;
    const isExist = await Operator.find({ _id: id }).populate(['doctorid','clinicid'])
    if (isExist.length > 0) {
      res.send(isExist)
    } else {
      res.send("No operator found");
    }
  });
于 2021-09-27T13:01:40.263 回答