多行值范围的交集

问题描述 投票:0回答:1

假设我们有一个包含 6 列的 mongodb 集合:

  • 房间来自
  • 房间
  • 池来自
  • 池到
  • 楼层自
  • 楼层

现在我想选择范围*From / *与另一个范围相交的行。

例如:

[
  {
    _id: 1,
    RoomFrom: 100,
    RoomTo: 200,
    PoolFrom: 150,
    PoolTo: 155,
    FloorFrom: 170,
    FloorTo: 180
  },
  {
    _id: 2,
    RoomFrom: 150,
    RoomTo: 300,
    PoolFrom: 170,
    PoolTo: 200,
    FloorFrom: 170,
    FloorTo: 180
  },
  {
    _id: 3,
    RoomFrom: 210,
    RoomTo: 230,
    PoolFrom: 100,
    PoolTo: 110,
    FloorFrom: 500,
    FloorTo: 505
  },
  {
    _id: 4,
    RoomFrom: 300,
    RoomTo: 350,
    PoolFrom: 400,
    PoolTo: 450,
    FloorFrom: 600,
    FloorTo: 650
  },
  {
    _id: 5,
    RoomFrom: 400,
    RoomTo: 401,
    PoolFrom: 500,
    PoolTo: 503,
    FloorFrom: 700,
    FloorTo: 711
  }
]

现在我们有了范围:

范围变体#1

  • 房间来自 = 201
  • 房间= 350

所以在这个范围内我的结果中有对象:

  • 对象#2
  • 对象#3
  • 对象#4

本例中“find”的查询是什么?

我有来自Yong Shun的很好的例子(非常感谢!!!):

但这只是针对一种情况...

范围变体#2

  • 房间来自 = 201
  • 房间= 350
  • 池来自 = 100
  • 池到= 350

所以在这个范围内我的结果中有对象:

  • 对象#2
  • 对象#3

本例中“find”的查询是什么?

范围变体#3

  • 房间来自 = 201
  • 房间= 350
  • 池来自 = 100
  • 池到= 350
  • 楼层从 = 180
  • 楼层至 = 185

所以在这个范围内我的结果中有对象:

  • 对象#2

本例中“find”的查询是什么?

这个 https://mongoplayground.net/p/LDvAlyERpXD 工作正常,但仅适用于一对 RoomFrom / RoomTo,这个适用于 3 对:https://mongoplayground.net/p/81MKW9AkelA

所以我需要查询每对的范围:

  • 来自

谢谢。

mongodb mongodb-query aggregation-framework intersection
1个回答
0
投票

使用这篇文章中的区间交集算法,我们可以看到,当任一区间的起点大于另一个区间的终点时,2 个交集不会重叠。我们可以使用

$not
来检查相反的情况,即发生重叠的情况。

在 MongoDB 中,这将类似于以下表达式:

{
  $not: {
    "$or": [
      {
        $gt: [
          "$$roomFromInput",
          "$RoomTo"
        ]
      },
      {
        $gt: [
          "$RoomFrom",
          "$$roomToInput"
        ]
      }
    ]
  }
}

剩下的工作只是对游泳池和地板重复它,我们可以使用

$and
将它们链接起来。在这里,我使用
$let
来组织变量。

db.collection.aggregate([
  {
    "$match": {
      $expr: {
        $let: {
          vars: {
            roomFromInput: 201,
            roomToInput: 350,
            poolFromInput: 100,
            poolToInput: 350,
            floorFromInput: 180,
            floorToInput: 185
          },
          in: {
            $and: [
              //room
              {
                $not: {
                  "$or": [
                    {
                      $gt: [
                        "$$roomFromInput",
                        "$RoomTo"
                      ]
                    },
                    {
                      $gt: [
                        "$RoomFrom",
                        "$$roomToInput"
                      ]
                    }
                  ]
                }
              },
              //pool
              {
                $not: {
                  "$or": [
                    {
                      $gt: [
                        "$$poolFromInput",
                        "$PoolTo"
                      ]
                    },
                    {
                      $gt: [
                        "$PoolFrom",
                        "$$poolToInput"
                      ]
                    }
                  ]
                }
              },
              //floor
              {
                $not: {
                  "$or": [
                    {
                      $gt: [
                        "$$floorFromInput",
                        "$FloorTo"
                      ]
                    },
                    {
                      $gt: [
                        "$FloorFrom",
                        "$$floorToInput"
                      ]
                    }
                  ]
                }
              }
            ]
          }
        }
      }
    }
  }
])

蒙戈游乐场


注:

  1. 这假设输入间隔格式正确。 (即开始小于结束,这些值是有效数字...)
  2. 这假设文档中的字段格式良好。 (即是数字/不是字符串,没有缺失/空字段...)
© www.soinside.com 2019 - 2024. All rights reserved.