【问题标题】:Multiple condition with $lookup aggregation具有 $lookup 聚合的多个条件
【发布时间】:2018-12-04 02:10:19
【问题描述】:

我正在考虑使用最佳实践来解决 Mongoose 的以下问题。

我有三个模式:

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);
      };
    });
  });
}

我怎样才能最好地处理它?

【问题讨论】:

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


    【解决方案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"
      }}
    ])
    

    【讨论】:

      猜你喜欢
      • 2020-08-02
      • 2020-10-02
      • 2014-12-12
      • 2022-11-29
      • 2021-02-22
      • 1970-01-01
      • 2019-10-11
      • 2017-10-08
      • 1970-01-01
      相关资源
      最近更新 更多