代码之家  ›  专栏  ›  技术社区  ›  Nargis

MongoDB:从开始日期和结束日期数组中匹配特定日期的聚合查询

  •  0
  • Nargis  · 技术社区  · 1 年前

    我有一个mongodb用户集合。用户可以随时激活和停用自己。我正在存储每次激活的开始和结束日期。现在我想获得在特定日期活动的用户列表。

    一张唱片是这样的:

    {
      "active" : true,
      "endDates" : [
         16.11.2021,
         27.06.2020
      ],
      "startDates" : [
        21.10.2022,
        16.10.2021,
        09.04.2020
      ]   
    }
    

    在上面的示例中,startDates大于endDates,因为用户当前处于活动状态。

    现在,如果我想检查用户是否在上处于活动状态 12.05.2020 22.11.2022 ,应返回true,但应返回false 17.12.2021 .

    我试着在endDates和startDates上都这样使用放松:

    collection
      .aggregate([
        { $match: {} },
        { $unwind: '$endDates' },
        { $unwind: '$startDates' },
      ])
    

    但它给了我开始和结束日期的所有可能组合,并返回了6个文档,这对查找日期范围没有帮助。

    1 回复  |  直到 1 年前
        1
  •  2
  •   nimrod serok    1 年前

    格式化数据的一个选项是使用 $dateFromString 将这些字符串格式化为正确的日期,以及 $zip 具有 $reverseArray 以正确的顺序将它们配对:

    db.collection.aggregate([
      {$project: {
          endDates: {
            $map: {
              input: "$endDates",
              in: {$dateFromString: {
                  dateString: "$$this",
                  format: "%d.%m.%Y"
              }}
            }
          },
          startDates: {
            $map: {
              input: "$startDates",
              in: {$dateFromString: {
                  dateString: "$$this",
                  format: "%d.%m.%Y"
              }}
            }
          }
      }},
      {$project: {
          dates: {
            $zip: {
              inputs: [
                {$reverseArray: "$startDates"},
                {$reverseArray: "$endDates"}
              ],
              useLongestLength: true
            }
          }
      }}
    ])
    

    看看它是如何在 playground example

    现在,如果你想检查一个特定的日期,你可以再添加一个步骤到 $filter 您的数组,并将结果替换为布尔值:

    {$project: {
          res: {
            $toBool: {$size: {
                $filter: {
                  input: "$dates",
                  cond: {
                    $and: [
                      {$gte: [ISODate("2021-12-17T00:00:00Z"), {$first: "$$this"}]},
                      {$or: [
                          {$lt: [ISODate("2021-12-17T00:00:00Z"), {$last: "$$this"}]},
                          {$eq: [{$last: "$$this"}, null]}
                      ]}
                    ]
                  }
                }
            }}
          }
      }}
    

    看看它是如何在 playground example