【问题标题】:How to query on two arrays at the same time in MongoDB?如何在 MongoDB 中同时查询两个数组?
【发布时间】:2021-12-30 04:55:59
【问题描述】:

我有以下文档,其中每个文档都有字段valuesdates,它们是数组。这些数组在每个文档中始终具有相同的大小,这意味着dates 中的每个值都对应于values 中的一个值:

[
  {
    _id: "Stock1",
    values: [
      1,
      2,
      3
    ],
    dates: [
      ISODate("2000-01-01"),
      ISODate("2010-01-01"),
      ISODate("2020-01-01")
    ]
  },
  {
    _id: "Stock2",
    values: [
      4,
      5,
    ],
    dates: [
      ISODate("2000-01-01"),
      ISODate("2010-01-01")
    ]
  },
  {
    _id: "Stock3",
    values: [
      7,
      8,
      9
    ],
    dates: [
      ISODate("2000-01-01"),
      ISODate("2010-01-01"),
      ISODate("2020-01-01")
    ]
  }
]

我想查询我的文档,以便在“Stock1”和“Stock3”的dates“2010-01-01”和dates“2020-01-01”(包括)之间获得values仅,即我想最终得到:

[
  {
    _id: "Stock1",
    values: [
      2,
      3
    ],
    dates: [
      ISODate("2010-01-01"),
      ISODate("2020-01-01")
    ]
  },
  {
    _id: "Stock3",
    values: [
      8,
      9
    ],
    dates: [
      ISODate("2010-01-01"),
      ISODate("2020-01-01")
    ]
  }
]

目前,我正在做以下事情:

db.collection.aggregate([
  {
    $match: {
      _id: {
        $in: [
          "Stock1",
          "Stock3"
        ]
      }
    }
  },
  {
    $unwind: {
      path: "$dates",
      includeArrayIndex: "date_index"
    }
  },
  {
    $match: {
      dates: {
        $gte: ISODate("2010-01-01"),
        $lte: ISODate("2020-01-01")
      }
    }
  },
  {
    $unwind: {
      path: "$values",
      includeArrayIndex: "value_index"
    }
  },
  {
    $match: {
      $expr: {
        $eq: [
          "$date_index",
          "$value_index"
        ]
      }
    }
  },
  {
    $project: {
      date_index: 0,
      value_index: 0
    }
  }
])

但我还没到那一步。此外,管道看起来很长且次优。有没有更好的方法来做到这一点?最后,我首先在dates 上使用unwind,然后在values 上再次使用unwind 之前进行过滤:这是为了避免管道中的一些文档太大,因为数组dates 和@987654336 @ 可能很大。

任何帮助将不胜感激!

【问题讨论】:

    标签: arrays mongodb mongodb-query nosql document


    【解决方案1】:

    查询

    • 匹配只保留"Stock1","Stock3"
    • 过滤日期索引(range (size "$dates")),只获取日期在[2010-2020]范围内的元素的索引
    • 2 映射以从 datesvalues 获取那些过滤后的索引

    *我们可以像 1 reduce 一样做所有事情,但它会是嵌套的和更复杂的代码,而且$concatArrays 很慢,将数组减少为数组并不是一个好主意。波纹管更简单,甚至可以工作非常大数组。

    Test code here

    aggregate(
    [{"$match": {"_id": { "$in": ["Stock1","Stock3"]}}}
     {"$set": 
        {"indexes": 
          {"$filter": 
            {"input": {"$range": [0, {"$size": "$dates"}]},
              "cond": 
              {"$and": 
                [{"$gte": 
                    [{"$arrayElemAt": ["$dates", "$$this"]},
                      ISODate("2010-01-01T00:00:00Z")]},
                  {"$lte": 
                    [{"$arrayElemAt": ["$dates", "$$this"]},
                      ISODate("2020-01-01T00:00:00Z")]}]}}}}},
      {"$set": 
        {"dates": 
          {"$map": 
            {"input": "$indexes",
              "in": {"$arrayElemAt": ["$dates", "$$this"]}}}}},
      {"$set": 
        {"values": 
          {"$map": 
            {"input": "$indexes",
              "in": {"$arrayElemAt": ["$values", "$$this"]}}}}},
      {"$unset": ["indexes"]}])
    

    【讨论】:

      猜你喜欢
      • 2017-11-18
      • 2016-01-29
      • 1970-01-01
      • 2021-07-01
      • 1970-01-01
      • 2021-09-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多