【问题标题】:MongoDB store and query price historyMongoDB 存储和查询价格历史
【发布时间】:2019-09-16 14:47:48
【问题描述】:

我正在处理一组数据,即产品目录。只有大约 20k 件商品,价格变化很少发生。每月最多可能有 100 次更新。

但是,在这种情况下,价格变化是有趣的事情,我想长期跟踪价格。

我正在努力寻找以易于查询的方式存储价格数据的最佳方式。

目前它存储在产品文档的数组中。只是价格和时间戳。鉴于少量且相当静态的数据集,您将如何设计模型?

另外,还有一个额外的问题,一个过滤器会是什么样子,可以提供当前价格低于前一个价格的产品列表?

示例数据,模型的简化版:

// Match, current price is lower than previous price

db.TestC.insert({Name: "P1", CurrentPrice: 10.0,  PriceHistory: [{Price: 14.0, Timestamp: ISODate("2019-04-26T07:11:11.939Z")}, {Price: 12.0, Timestamp: ISODate("2019-04-27T07:11:11.939Z")}]})

// No match, price history doesn't exist yet

db.TestC.insert({Name: "P2", CurrentPrice: 10.0, PriceHistory: null})

// No match, previous price was lower than current price

db.TestC.insert({Name: "P3", CurrentPrice: 18.0, PriceHistory: [{Price: 14.0, Timestamp: ISODate("2019-04-26T07:11:11.939Z")}, {Price: 12.0, Timestamp: ISODate("2019-04-27T07:11:11.939Z")}]})

在对此进行更多工作后进行编辑:

所以,我终于想出了我需要的东西,并认为我应该分享一下,以防它对某人有所帮助:

db.TestCollection.aggregate({
    '$project': {
      'Number': 1, 
      'AssortmentKey': 1, 
      'AssortmentName': 1, 
      'NameExtension': 1, 
      'Name': 1, 
      'CurrentPrice': {
        '$arrayElemAt': [
          '$PriceHistory', -1
        ]
      }, 
      'PreviousPrice': {
        '$arrayElemAt': [
          '$PriceHistory', -2
        ]
      }
    }
  }, {
    '$match': {
      '$expr': {
        '$lt': [
          '$CurrentPrice.Price', '$PreviousPrice.Price'
        ]
      }
    }
  })

【问题讨论】:

    标签: mongodb mongodb-query


    【解决方案1】:

    我实际上会以相同的方式组织文档。请记住,MongoDB 对每个文档有 16 MB 的硬限制,这是非常非常高的限制,在这种情况下几乎无法访问,但它仍然存在。

    如果您只需要知道当前价格而不知道历史,您可以使用投影查询,以避免通过网络发送庞大的数组:

    db.TestC.find({Name: 'P1'}, {Name, CurrentPrice}});
    

    至于额外问题,您可以利用聚合框架:

    db.TestC.aggregate([
      {
        $project: {
          Name: 1,
          CurrentPrice: 1,
          PreviousPrice: { // remove this key if you don't need to have previous price in the result
            $arrayElemAt: [
              "$PriceHistory",
              0 // depends on whether you store prices by pushing to the end of history array, or to the beginning of it
            ]
          },
          IsCurrentPriceLower: {
            $lt: [
              "$CurrentPrice",
              {
                $arrayElemAt: [
                  "$PriceHistory",
                  0 // depends on whether you store prices by pushing to the end of history array, or to the beginning of it
                ]
              }
            ]
          }
        },
      },
      {
        $match: {
          IsCurrentPriceLower: true
        }
      }
    ])
    

    【讨论】:

    • 太好了,谢谢!至于大小限制,我认为这不是问题:) 另外,我认为我需要将 lt 更改为 gt 或交换比较项目的顺序以获得所需的结果?
    猜你喜欢
    • 1970-01-01
    • 2016-11-19
    • 1970-01-01
    • 1970-01-01
    • 2018-02-24
    • 2016-04-11
    • 2012-03-27
    • 2011-03-23
    • 1970-01-01
    相关资源
    最近更新 更多