【问题标题】:how to reduce unnecessary unwind stages from aggregation pipeline如何减少聚合管道中不必要的展开阶段
【发布时间】:2020-08-20 16:00:39
【问题描述】:

如果我在聚合管道中应用了许多查找阶段,并且每次查找之后都有一个展开(只是为了隐藏到对象)第一个问题它会影响查询性能吗?如果是的话,如何以优化的方式做到这一点

注意:所有查找将只返回一个对象

例如:

xyz.aggregate([
{ $lookup:{ ----}} //first lookup
{$unwind :{----}} //first unwind
{ $lookup:{ ----}} //second lookup
{$unwind :{----}} //second unwind
{ $lookup:{ ----}} //third lookup
{$unwind :{----}} //third unwind
{ $lookup:{ ----}} //fourth lookup
{$unwind :{----}} //fourth unwind
])

【问题讨论】:

  • 由于lookup 阶段太多,我建议您将它们全部替换为一个但advanced 具有管道选项的查找。
  • 每次查找是否返回一个文档?
  • @TheeSritabtim 您仍然可以使用高级查找,即使它们来自不同的集合,因为我自己已经完成了,即 5 个不同的集合。就性能而言,mongo 端肯定存在一些 bug 或其他问题。
  • 只是一个想法,如果我们添加新的单个项目阶段来替换所有展开,我们可以简单地在 0 索引(第一个元素)处投影元素,这值得尝试吗?
  • 如果查找返回超过 1 个文档,将它们全部展开将导致复制所有其他文档。因此,如果 4 次查找中的每一次都返回 2 个文档,则输出中将有 16 个文档。将 $addFields 与 $arrayElemAt 一起使用将允许您只获取第一个文档而没有风险。

标签: mongodb optimization mongoose aggregation-framework


【解决方案1】:

参考cmets,这里是高级$lookup

$lookup: {
        from: 'accounts',
        let: { "localAccountField": "$account" },
        pipeline: [
          {
            $match: {
              $expr: {
                $eq: ["$_id", "$$localAccountField"]
              }
            }
          },
          {
            $project: {
              _id: 1,
              user: 1
            }
          },
          {
            $lookup: {
              from: 'users',
              let: { 'localUserField': "$user" },
              pipeline: [
                {
                  $match: {
                    $expr: {
                      $eq: ["$_id", "$$localUserField"]
                    }
                  }
                },
                {
                  $project: {
                    _id: 1,
                    username: "$uid",
                    phone:"$phoneNumber",
                    email: "$email.add",
                    name: {
                      $concat: [
                        "$profile.name.first",
                        ' ',
                        "$profile.name.last"
                      ]
                    },
                  }
                }
              ],
              as: "users"
            }
          },
          {
            $lookup: {
              from: 'documents',
              let: { 'localDocumentField': "$user" },
              pipeline: [
                {
                  $match: {
                    $expr: {
                      $eq: ["$user", "$$localDocumentField"]
                    },
                    status:"verified",
                    "properties.expirydate": { $exists: true, $ne: "" },
                    name: "idcard"
                  }
                },
                {
                  $project: {
                    _id: 0,
                    cnic: "$properties.number"
                  }
                }
              ],
              as: "documents"
            }
          }
        ],
        as: 'account'
      }

【讨论】:

  • 谢谢它真的很有帮助!
猜你喜欢
  • 1970-01-01
  • 2020-09-20
  • 2019-06-03
  • 1970-01-01
  • 2020-10-16
  • 2021-07-30
  • 2019-01-04
  • 1970-01-01
  • 2017-09-20
相关资源
最近更新 更多