mongodb 将合并两个mongoose聚合管道合并为一个,其中第一个管道的结果用于另一个管道

o7jaxewo  于 2023-11-17  发布在  Go
关注(0)|答案(1)|浏览(144)

我有一个名为dummy的集合。它的模式定义为-

const schema = mongoose.Schema(
{
    Name: { type: String },
    start: { type: String },
    end: { type: String },
}

字符串
现在我想从end < x的集合中获取文档。但这里有一个问题-
1.从文档匹配上面的过滤器我不想要那些文档的Name,我们可以找到另一个文档,其中start<=x<=end
1.对于每个Name,只应该在end最接近x的地方获取一个文档。
我可以在多个聚合管道中实现这一点,方法是在第一个聚合管道中获取namesArr中的所有Name,其中start<=x<=end,然后使用{$nin:namesArr}删除具有这些名称的文档,然后按Name分组,并以降序排序插入所有文档,并首先选择在第二个聚合管道中end最接近x的每个总线只获取一个文档。示例集合-

{Name : 'a', start :30, end :35},
{Name : 'a', start :40, end :50},
{Name : 'b', start :10, end :25},
{Name : 'b', start :30, end :35},
{Name : 'b', start :60, end :80},


所以如果x是44,那么查询应该只返回{Name : 'b', start :30, end :35}
但是我想在单个聚合管道中实现这一点,因为我不想首先获取namesArr,然后将其传递到第二个聚合管道中。

v1l68za4

v1l68za41#

我们可以通过计算4个辅助字段来实现所需的行为。

  1. isInRange:boolean,表示start<=x<=end是否
  2. diffToX:数字,表示xend的绝对差值通过对Name字段进行分组,我们得到了2个聚合的辅助字段
  3. anyInRange:boolean,通过使用$max,我们检查是否有任何isInRangeName组中。如果任何条目在范围内,最终结果为true;否则为false。
  4. rank:int,通过对diffToX进行排序来计算排名。最接近X的条目应该具有最高的排名(即最小的排名数)
    通过使用4个辅助字段,我们可以在以下步骤中获得您期望的结果:
    1.计算每个文档的isInRangediffToX
    1.使用"partitionBy": "$Name""sortBy": {"diffToX": 1}$setWindowFields中计算anyInRangerank
  5. $match with end <= X and anyInRange:false
  6. $sort,rank:1和$limit: 1,以获得最接近X的条目
db.collection.aggregate([
  {
    $set: {
      isInRange: {
        "$cond": {
          "if": {
            $let: {
              vars: {
                x: 44
              },
              in: {
                $and: [
                  {
                    $lte: [
                      "$start",
                      "$$x"
                    ]
                  },
                  {
                    $gte: [
                      "$end",
                      "$$x"
                    ]
                  }
                ]
              }
            }
          },
          "then": true,
          "else": false
        }
      },
      diffToX: {
        "$abs": {
          "$subtract": [
            "$end",
            44
          ]
        }
      }
    }
  },
  {
    "$setWindowFields": {
      "partitionBy": "$Name",
      "sortBy": {
        "diffToX": 1
      },
      "output": {
        "anyInRange": {
          "$max": "$isInRange"
        },
        "rank": {
          "$rank": {}
        }
      }
    }
  },
  {
    "$match": {
      end: {
        $lt: 44
      },
      anyInRange: false
    }
  },
  {
    $sort: {
      rank: 1
    }
  },
  {
    $limit: 1
  },
  {
    "$unset": [
      "anyInRange",
      "diffToX",
      "isInRange",
      "rank"
    ]
  }
])

字符串
Mongo Playground

相关问题