【问题标题】:How to match Array elements in Sub-Documents by Criteria如何按条件匹配子文档中的数组元素
【发布时间】:2017-04-23 09:23:50
【问题描述】:

我有以下 Mongoose 架构:

员工架构:

var EmployeeSchema = new Schema({
    name : String,
    employeeDetailsId: {
        type: Schema.Types.ObjectId,
        ref: 'employeedetails'
    }
});

EmployeeDetailSchema:

var EmployeeDetailSchema = new Schema({
    employeeId: {
        type: Schema.Types.ObjectId,
        ref: 'employee'
    },
    primarySkills: [
    {
        type: Schema.Types.ObjectId,
        ref: 'skills'
    }
],
});

技能架构:

var SkillsSchema = new Schema({
    name: {
        type: String,
        required: true
    }
});

EmployeeDetailSchema 数据按需保存,例如将特定技能分配给员工时。一旦EmployeeDetail 文档被保存,则对应的EmployeeDetailID 将作为employeeDetailsId 保存回EmployeeSchema

现在EmployeeSchemaEmployeeDetailSchema 之间存在双向关系。

注意: 多个技能可以与一个员工相关联,它们在 EmployeeDetails Schema 中存储为 ObjectID 的数组。

用例:

我想获取所有与他们相关的特定技能的员工,技能将被输入到 Mongoose / Mongo 查询中。

假设输入技能 ID 为 1234,那么我想在 EmployeeDetail > PrimarySkills 数组中获取技能 ID 为 1234 的所有员工。

以下是我尝试使用 Mongoose 的方法:

EmployeeModel.aggregate([
    {
        $lookup: {
            from: 'employeedetails', 
            localField: 'employeeDetailsId',
            foreignField: '_id',
            as: 'details'
        }
    },
    {
        $match: { 
            $and: [
                { "details.primarySkills": { "$exists": true } },               
                { 
                    "details.primarySkills": { 
                        $in: [mongoose.Types.ObjectId(req.params.skillId)]                          
                    }
                }
            ]
        } 
    }
]).exec(function (err, result) {
    if (err) return res.send('400', {
        message: 'Unable to fetch employees data by status. Please try again later'
     });

     return res.jsonp(result);
});

结果:空数组。

我不知道哪里出了问题,需要一些帮助。

【问题讨论】:

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


    【解决方案1】:

    您可以采取的一种方法是先将$lookup 应用于EmployeeDetails 模型上的Skills 模型,然后再查找Employee 模型

    EmployeeDetails.aggregate([
        { "$match": { "primarySkills": req.query.skillId } },
        { "$unwind": "$primarySkills" }, // skip this pipeline step for MongoDB 3.4 and above
        {
            "$lookup": {
                "from": "skills",// ensure this is the correct collection name
                "foreignField": "_id",
                "localField": "primarySkills",
                "as": "skills"
            }
        },
        { "$unwind": "$skills" }
        {
            "$group": {
                "_id": "$_id",
                "employeeId": { "$first": "$employeeId" },
                "primarySkills": { "$push": "$skills" }
            }
        },
        {
            "$lookup": {
                "from": "employees",// ensure this is the correct collection name
                "foreignField": "_id",
                "localField": "employeeId",
                "as": "employee"
            }
        }
    ]).exec(callback);
    

    【讨论】:

      【解决方案2】:

      除了一个小错误外,我遵循的糟糕的原始方法都很好。我应该使用req.query.skillId 而不是req.params.skillId

      对于那些想知道黑白查询和参数的区别的人,请查看answer

      这是最终的解决方案,认为它可以帮助其他人:

      EmployeeModel.aggregate([
          {
              $lookup: {
                  from: 'employeedetails', 
                  localField: 'employeeDetailsId',
                  foreignField: '_id',
                  as: 'details'
              }
          },
          {
              $match: { 
                  $and: [
                      { "details.primarySkills": { "$exists": true } },               
                      { 
                          "details.primarySkills": { 
                              $in: [mongoose.Types.ObjectId(req.query.skillId)]                          
                          }
                      }
                  ]
              } 
          }
      ]).exec(function (err, result) {
          if (err) return res.send('400', {
              message: 'Unable to fetch employees data by status. Please try again later'
           });
      
           return res.jsonp(result);
      });
      

      【讨论】:

        猜你喜欢
        • 2011-12-19
        • 1970-01-01
        • 2022-01-09
        • 2019-06-21
        • 2019-02-16
        • 1970-01-01
        • 2016-07-13
        • 2017-05-18
        • 1970-01-01
        相关资源
        最近更新 更多