【问题标题】:How to populate in 3 collection in mongoDB with Mongoose如何使用 Mongoose 在 mongoDB 中填充 3 个集合
【发布时间】: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

标签: node.js mongodb mongoose mongodb-query aggregation-framework


【解决方案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();

【讨论】:

    猜你喜欢
    • 2019-08-07
    • 2020-09-10
    • 2019-06-25
    • 2014-07-17
    • 2015-06-30
    • 2017-08-23
    • 2019-05-26
    • 2020-01-31
    • 2016-05-07
    相关资源
    最近更新 更多