如何使用 Mongoose 在 mongoDB 中填充 3 个集合

Posted

技术标签:

【中文标题】如何使用 Mongoose 在 mongoDB 中填充 3 个集合【英文标题】:How to populate in 3 collection in mongoDB with Mongoose 【发布时间】:2019-01-14 10:13:36 【问题描述】:

我有三个集合,例如UserProgram 和`Agenda。这些模型如下。

用户模型

const mongoose = require('mongoose');

const UserSchema = mongoose.Schema(
    name: type:String,
    email: type:String
,timestamps:true

);

module.exports = mongoose.model('User', UserSchema);

程序模型

const mongoose = require('mongoose');

const NoteSchema = mongoose.Schema(
    name: type:String,
    timefrom: type:Date,
    timeto: type:Date,
    status: type:String,
    venue: type:String,
    timetype: type:Number,
    userid:type:mongoose.Schema.Types.ObjectId,ref : 'User', required: true,
    logo :type:String,default: 'programe'
,timestamps:true
);

module.exports = mongoose.model('Program', NoteSchema);

议程模型

const mongoose = require('mongoose');

const AgendaSchema = mongoose.Schema(
    name: type:String,
    timefrom: type:Date,
    timeto: type:Date,
    status: type:String,
    proorder: type:String,
    proid:type:mongoose.Schema.Types.ObjectId,ref : 'Program', required: true
,
timestamps:true
);

module.exports = mongoose.model('Agenda', AgendaSchema);

现在我只获得议程和节目数据。

议程控制者

// Retrieve and return all agenda from the database.
exports.findAll = (req, res) => 

    Agenda.find()
    .populate('proid')
    //.populate('userid')

    .then(agendas => 
        res.send(agendas);
    ).catch(err => 
        res.status(500).send(
            message: err.message || "Some error occurred while retrieving agenda."
        );
    );
;

当我转到此 URL 和 GET 方法时,我想填充 agenda 文档(完成)、相关的 program 文档(完成)和相关的 user 文档(我想要的)?

想要的查询是这样的

SELECT * 
FROM users, programs, agendas
WHERE agendas.proid = programs.id AND programs.userid = users.id

【问题讨论】:

你的mongodb版本是多少? MongoDB 版本是4.0.0 【参考方案1】:

您可以使用$lookup 聚合

Agenda.aggregate([
   "$lookup": 
    "from": Program.collection.name,
    "let":  "proid": "$proid" ,
    "pipeline": [
       "$match":  "$expr":  "$eq": [ "$_id", "$$proid" ]   ,
       "$lookup": 
        "from": User.collection.name,
        "let":  "userid": "$userid" ,
        "pipeline": [
           "$match":  "$expr":  "$eq": [ "$_id", "$$userid" ]   ,
        ],
        "as": "userid"
      ,
       "$unwind": "$userid" 
    ],
    "as": "proid"
  ,
   "$unwind": "$proid" 
])

或使用填充

Agenda.find()
  .populate([ path: 'proid', populate:  path: 'userid' ])

两者都会给你相同的结果

【讨论】:

populate 看起来更干净 @Hassaan 但是你不能使用populate 中的数据,从长远来看当然$lookup 是更好的解决方案 不成功,显示为较早的结果(仅议程数据和节目数据,不显示用户数据)。 干得好!谢谢@Anthony Winzlet @Anthony Winzlet,我可以从 pragrams 中获取所有三个集合的列表吗?这里我想通过localhost:3000/programes/id=1GET获取所有详细信息(这里我们可以通过填充轻松获取程序和用户详细信息,例如文档,但是如何获取议程详细信息,我们应该通过给定程序选择所有议程文档id )?【参考方案2】:

您可以使用.populate() populate : path : 'field' 。 示例:

Agenda.find().                    //Collection 1
        populate(path:'proid',   //Collection 2
        populate:path:'userid'   //Collection 3
        )
    .exec();

4个集合后,需要识别型号,如果不能错 示例:

    Agenda.find().                                    //Collection 1
        populate(path:'proid',                       //Collection 2
        populate:path:'userid',                      //Collection 3
        populate:path:'otherFiel', model: Collection //Collection 4 and more
        )
    .exec();

最后,如果您只想获取某个 Collection 的某些字段,您可以使用属性select 示例:

Agenda.find().                                    
        populate(path:'proid', select:'name status venue'                  
        populate:path:'userid'               
        )
    .exec();

【讨论】:

以上是关于如何使用 Mongoose 在 mongoDB 中填充 3 个集合的主要内容,如果未能解决你的问题,请参考以下文章

如何在 typescript 中使用 mongoose 在 mongodb 中插入数据?

如何使用 Mongoose 在 mongoDB 中填充 3 个集合

如何在 mongoose/mongodb 查询子文档中使用 mapreduce?

如何在 mongoose/mongodb 查询子文档中使用 mapreduce?

如何使用 Mongoose 在 mongodb 中存储动态对象数组?

如何使用 mongoose 在 MongoDB 数组中推送数据