首页 > 解决方案 > 查询数组数组

问题描述

我是 mongodb 的新手,现在已经被困在这个任务上一段时间了。我需要使用以下架构对集合执行查询:

{
  ticker: String,
  asks: [[Number]],
  bids: [[Number]],
  timestamp: String,
  datetime: String
}

这是文档示例:

  { 
    "_id" : ObjectId("5fc17630cf8dff0cd5506dc4"), 
    "asks" : [ 
      [ "23685.0", "0.008" ],
      [ "23688.8", "0.000" ],
      [ "23696.7", "0.000" ]
    ], 
    "bids" : [ 
      [ "23553.7", "0.200" ],
      [ "23557.8", "0.207" ],
      [ "23558.4", "0.045" ],
      [ "23563.4", "0.020" ] 
    ],
    "timestamp" : 1606514176211,
    "datetime" : "2020-11-27T21:56:16.211Z",
    "ticker" : "YFI/USDT"
  }

询问和投标的内部数组有两个元素:第一个元素是价格,第二个元素是数量。

我有两个问题:

  1. 我需要查询集合以获取价格大于基于日期时间字段的时间间隔的要价和出价(仅要价或仅出价)的所有条目。我试图弄乱 $elemMatch 和聚合框架,但到目前为止没有运气。

  2. 我的另一个问题是,在查询这些字段时,数组或数组字段类型是否是一个不错的选择。我希望有数百万条这种类型的记录。请建议是否添加索引和/或使用其他数据结构将这些数据保存在集合中。

任何帮助是极大的赞赏。谢谢。

标签: mongodbmongodb-queryaggregation-framework

解决方案


问题一:

您必须首先 $match 您的日期以仅返回所需时间间隔内的文档,然后 $filter 您的数组(询问或出价)以仅返回您需要的内容。

这是查询(当然,您可以对出价执行完全相同的操作):

db.collection.aggregate([
  {
    "$match": {
      $expr: {
        "$and": [
          {
            "$gte": [
              "$datetime",
              "2020-11-01"
            ]
          },
          {
            "$lt": [
              "$datetime",
              "2020-12-01"
            ]
          }
        ]
      }
    }
  },
  {
    "$addFields": {
      "asks": {
        "$filter": {
          "input": "$asks",
          "as": "ask",
          "cond": {
            "$gte": [
              {
                "$toDouble": {
                  "$arrayElemAt": [
                    "$$ask",
                    0
                  ]
                }
              },
              23686
            ]
          }
        }
      }
    }
  }
])

你可以在这里测试

问题2 :

但是,正如您所注意到的,这可能不是存储和查询数据的最佳方式。我看到了一些需要改进的简单事情:

1-用一个对象替换你的嵌套数组。直接查询对象字段而不是数组中的位置会更容易。

{
  "price" : yourPrice, 
  "quantity":yourQuantity
}

2-使用数字(int / double)而不是字符串,您将避免转换步骤,从而提高聚合的性能。

{
  "price" : 21563, 
  "quantity":0.154
}

3-你真的需要日期和时间吗?如果没有,只需存储日期,以便您可以在其上放置索引并在 $match 阶段利用它。

这是此类数据集/查询的示例


推荐阅读