【问题标题】:express mongoose populate issue表达猫鼬填充问题
【发布时间】:2019-12-06 23:52:26
【问题描述】:

我有 2 个模型,我正在尝试使用填充函数来获得整理的响应。

我的模型如下

const mongoose = require('mongoose');

const RegisterEmpSchema = new mongoose.Schema({
    empID: Number,
    empName: String,
    empPhone: String,
    empProj: String
}, {
    timestamps: true
});

const RegisterEntriesSchema = new mongoose.Schema({
    registerType: String,
    registerItemsQuantity: Number,
    registerItemsDesc: String,
    empID: {
        type: mongoose.Schema.Types.Number,
        ref: 'registerEmpModel'
    }
}, {
    timestamps: true
});

RegisterEntriesSchema.index({ createdAt: 1 }, { expires: '525601m' });

const registerEmpModel = mongoose.model('RegisterEmpSchema', RegisterEmpSchema, 'registerEmployeeCollection');
const registerEntriesModel = mongoose.model('RegisterEntriesSchema', RegisterEntriesSchema, 'registerEntriesCollection');

module.exports = {
    registerEmpModel, registerEntriesModel,
}

当我尝试从 registerEntries 获取所有条目时,它只返回 registerEntries 并且不会使用 registerEmp 值填充响应

// Retrieve and return all registers from the database.
exports.findAllRegisterEntries = (req, res) => {

    registerEntriesModel.
        find().
        populate('RegisterEmpSchema').
        exec(function (err, data) {
            if (err) return console.log(err);
            res.send(data);
        });
};

我保存模型数据的控制器代码https://pastebin.com/fj84azkM

【问题讨论】:

标签: node.js mongodb express mongoose


【解决方案1】:

我认为您不能在这种情况下使用填充,因为您正在尝试填充 empID 字段,但猫鼬不知道 empID 是员工模型中的 empID,默认情况下它会尝试在 _id 上匹配此 empID员工模型的字段。

解决此问题的一种方法是在员工架构中使用 _id 字段而不是 empID 字段:

const RegisterEmpSchema = new mongoose.Schema(
  {
    _id: mongoose.Schema.Types.Number,
    empName: String,
    empPhone: String,
    empProj: String
  },
  {
    timestamps: true
  }
);

并使用此示例正文创建员工:

{
    "_id": 1,
    "empName": "emp 1 name",
    "empPhone":"emp 1 phone",
    "empProj": "emp 1 proj"
}

现在您可以像这样填充:

exports.findAllRegisterEntries = (req, res) => {

  registerEntriesModel
    .find()
    .populate("empID")   // note that here we use the fieldName
    .exec(function(err, data) {
      if (err) return console.log(err);
      res.send(data);
    });
};

结果如下:

[
    {
        "_id": "5dea4f795668341d0cb51a46",
        "registerType": "register type 1",
        "registerItemsQuantity": 1,
        "registerItemsDesc": "register desc",
        "empID": {
            "_id": 1,
            "empName": "emp 1 name",
            "empPhone": "emp 1 phone",
            "empProj": "emp 1 proj",
            "createdAt": "2019-12-06T12:54:06.446Z",
            "updatedAt": "2019-12-06T12:54:06.446Z",
            "__v": 0
        },
        "createdAt": "2019-12-06T12:54:17.986Z",
        "updatedAt": "2019-12-06T12:54:17.986Z",
        "__v": 0
    },
    {
        "_id": "5dea4f7b5668341d0cb51a47",
        "registerType": "register type 2",
        "registerItemsQuantity": 2,
        "registerItemsDesc": "register desc",
        "empID": {
            "_id": 2,
            "empName": "emp 2 name",
            "empPhone": "emp 2 phone",
            "empProj": "emp 2 proj",
            "createdAt": "2019-12-06T12:54:14.762Z",
            "updatedAt": "2019-12-06T12:54:14.762Z",
            "__v": 0
        },
        "createdAt": "2019-12-06T12:54:19.930Z",
        "updatedAt": "2019-12-06T12:54:19.930Z",
        "__v": 0
    }
]

作为第二种选择,如果您不想对架构进行任何更改,您可以像这样使用聚合:

router.get("/entry", async (req, res) => {
  const result = await registerEntriesModel.aggregate([
    {
      $lookup: {
        from: "registerEmployeeCollection",
        localField: "empID",
        foreignField: "empID",
        as: "employee"
      }
    },
    {
      $addFields: { employee: { $arrayElemAt: ["$employee", 0] } }
    }
  ]);

  res.send(result);
});

这将给出这样的输出:

[
    {
        "_id": "5dea49170817b24bb8f37665",
        "registerType": "register type 1",
        "registerItemsQuantity": 1,
        "registerItemsDesc": "register desc",
        "empID": 1,
        "createdAt": "2019-12-06T12:27:03.841Z",
        "updatedAt": "2019-12-06T12:27:03.841Z",
        "__v": 0,
        "employee": {
            "_id": "5dea49020817b24bb8f37663",
            "empID": 1,
            "empName": "emp 1 name",
            "empPhone": "emp 1 phone",
            "empProj": "emp 1 proj",
            "createdAt": "2019-12-06T12:26:42.213Z",
            "updatedAt": "2019-12-06T12:26:42.213Z",
            "__v": 0
        }
    },
    {
        "_id": "5dea491e0817b24bb8f37666",
        "registerType": "register type 2",
        "registerItemsQuantity": 2,
        "registerItemsDesc": "register desc",
        "empID": 2,
        "createdAt": "2019-12-06T12:27:10.696Z",
        "updatedAt": "2019-12-06T12:27:10.696Z",
        "__v": 0,
        "employee": {
            "_id": "5dea490b0817b24bb8f37664",
            "empID": 2,
            "empName": "emp 2 name",
            "empPhone": "emp 2 phone",
            "empProj": "emp 2 proj",
            "createdAt": "2019-12-06T12:26:51.130Z",
            "updatedAt": "2019-12-06T12:26:51.130Z",
            "__v": 0
        }
    }
]

【讨论】:

    【解决方案2】:

    这里ref 是集合名称:

    const RegisterEntriesSchema = new mongoose.Schema({
        registerType: String,
        registerItemsQuantity: Number,
        registerItemsDesc: String,
        empID: {
            type: mongoose.Schema.Types.ObjectId,
            ref: 'registerEmpModel' // Collection name
        }
    }, {
        timestamps: true
    });
    

    而且你必须填充字段而不是模型:

    registerEntriesModel.
            find().
            populate('empID').
            exec(function (err, data) {
                if (err) return console.log(err);
                res.send(data);
            });
    

    【讨论】:

    • @ViVekH 你试过看看这行得通吗?我认为这行不通。
    • 我修改了模型架构以引用 objectID 而不是数字
    猜你喜欢
    • 2015-07-13
    • 2016-10-10
    • 2020-02-23
    • 2019-09-16
    • 2015-07-13
    • 2020-01-17
    • 1970-01-01
    • 2021-05-03
    相关资源
    最近更新 更多