$ lookup聚合的多重条件

时间:2018-12-01 18:03:44

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

我正在考虑对猫鼬使用以下问题的最佳实践。

我有三种模式:

const SchemaA = new Schema({
  name: String
});

const SchemaB = new Schema({
  schemaA: {
    type: Schema.Types.ObjectId,
    ref: 'SchemaA',
    required: true
  }
});

const SchemaC = new Schema({
  schemaB: {
    type: Schema.Types.ObjectId,
    ref: 'SchemaB'
  },
  user: {
    type: Schema.Types.ObjectId,
    ref: 'User'
  }
});

我需要通过附加了schemaC的schemaA id来获取schemaB对象,但必须由用户过滤。

getSchemaBs: async (schemaAId, userId) => {
  try {
    SchemaB.find({ schemaA: schemaAId }).populate('schemaC': where user === userId);
  } catch (e) {
    throw new Error('An error occurred while getting schemasB for specified schemaA.');
  };

我正在重构使用针对NodeJS的Mongo本机驱动程序编写的代码。现在,我想使用Mongoose使其更简单。

早期版本的代码(请记住,它不能遵循最佳实践):

getList: function (schemaAId, userId) {
  return new Promise(
    function (resolve, reject) {
      db.collection('schemaB').aggregate([{
        $match: {
          'isDeleted': false,
          'schemaA': ObjectID(schemaAId)
        }
      },
      {
        $lookup: {
          from: "schemaC",
          localField: "_id",
          foreignField: "schemaBId",
          as: "schemasC"
        },
      },
      {
        $project: {
          _id: true,
          schemaAId: true,
          // other neccessary fields with true (several lines - makes code ugly and messy)
          schemasC: {
            "$arrayElemAt": [{
              $filter: {
                input: "$schamasC",
                as: "schemaC",
                cond: {
                  $eq: ["$$schemaC.userId", ObjectID(userId)]
                }
              }
            }, 0]
          }
        }
      }
    ]).toArray(function (error, result) {
      if (error) {
        reject(error);
      } else {
        resolve(result);
      };
    });
  });
}

我该如何处理最好的方法?

1 个答案:

答案 0 :(得分:1)

使用mongodb 3.6 $lookup语法可以更好地完成您想做的事情,该语法可以过滤$lookup管道内的文档

db.collection('schemaB').aggregate([
  { "$match": { "isDeleted": false, "schemaA": ObjectID(schemaAId) }},
  { "$lookup": {
    "from": "schemaC",
    "let": { "schemaBId": "$_id" },
    "pipeline": [
      { "$match": {
        "$expr": { "$eq": ["$schemaBId", "$$schemaBId"] },
        "userId": ObjectID("5b5c747d8209982630bbffe5")
      }}
    ],
    "as": "schemasC"
  }}
])