多个填充物 - mongoosejs

mrz*_*myr 38 javascript mongoose mongodb node.js

只是一个简单的查询,例如在模型中使用双引用.

架构/模型

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);
Run Code Online (Sandbox Code Playgroud)

询问

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

我已经尝试过类似的东西

.populate('user meal')
.populate(['user', 'meal'])
Run Code Online (Sandbox Code Playgroud)

实际上只有一个填充物可以工作.

那么,如何让两个填充工作?

Joh*_*yHK 38

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

OrderModel.find()
    .populate('user')
    .populate('meal')
    .exec(function (err, results) {
         // callback
    });
Run Code Online (Sandbox Code Playgroud)

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


Mic*_*hli 26

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

ORIGINAL POST
如果你使用的是Mongoose> = 3.6,你可以传递空格分隔的路径名字符串来填充:

OrderModel.find()
    .populate('user meal')
    .exec(function (err, results) {
         // callback
    });
Run Code Online (Sandbox Code Playgroud)

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

  • 确实简洁,但在我看来,每个人一条路径使其更具可读性。 (3认同)

Nen*_*vic 18

您可以使用array语法:

let results = await OrderModel.find().populate(['user', 'meal']);
Run Code Online (Sandbox Code Playgroud)

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

let results = await OrderModel.find().populate(['user', 'meal']);
Run Code Online (Sandbox Code Playgroud)


小智 7

这可能已经解决了,但这是我对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
    }
});
Run Code Online (Sandbox Code Playgroud)

可能还有其他方法可以做到这一点,但这对于初学者(如我)来说,代码很可读

  • 将数组放入填充调用中非常具有可读性。FWIW 您不需要该模型,除非您可能想调用不同的模型。`.populate([{path: '用户'}, {path: '餐'}])` (3认同)

小智 5

你可以试试:

OrderModel.find()
    .populate('user')
    .populate('meal')
    .exec(function (err, results) {
         // callback
    });
Run Code Online (Sandbox Code Playgroud)

或使用数组选项

OrderModel.find()
    .populate([
      {
        path: "path1",
        select: "field",
        model: Model1
      },
      {
        path: "path2",
        select: "field2",
        model: Model2
      }
    ])
    .exec(function (err, results) {
         // callback
    });
Run Code Online (Sandbox Code Playgroud)


Mat*_*man 5

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

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'
                            }]
                        }
                    }]);
Run Code Online (Sandbox Code Playgroud)

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


Swa*_*oni 5

最新的猫鼬v5.9.15 能够获取填充字段的数组,因此您可以这样做,

.populate([ 'field1', 'field2' ])
Run Code Online (Sandbox Code Playgroud)