【问题标题】:How to get list of documents which are deduplicated (on timestamp - latest wins) if the document has a specific key?如果文档具有特定键,如何获取已删除重复的文档列表(在时间戳上 - 最新获胜)?
【发布时间】:2019-12-15 10:44:58
【问题描述】:

我想在 cloudant 分区数据库(描述为 here)中使用只写(不可变)文档策略,其中对于每次文档更新,我都会创建一个包含更新字段的新文档。例如:数据库由订单组成(带有字段 order_id、details、time_of_doc_creation)。假设需要更新某个订单的详细信息 - 我创建一个包含更新数据并保留 order_id 的新文档。现在在某个时间点,我想查看系统中的所有订单,如果存在 order_id 相同的文档,那么只有日期最晚的文档才会出现在列表中。

我能想到的唯一方法是从数据库中提取所有文档,然后在客户端自己进行过滤,但是我可以在数据库本身中使用一些东西来获得这样的结果吗?

db中的订单列表:

{
order_id:1,
details:"old",
time:"1"
},
{
order_id:2,
details:"old",
time:"2"
},
{
order_id:1,
details:"new",
time:"3"
},
{
order_id:2,
details:"new",
time:"4"
}

期望的输出:给我系统中所有的订单文件,所以db输出应该是这样的->

{
order_id:1,
details:"new",
time:"3"
},
{
order_id:2,
details:"new",
time:"4"
}

【问题讨论】:

    标签: couchdb cloudant


    【解决方案1】:

    使用不可变模型通常可以发挥 Cloudant 的优势,但并不总是可行甚至是不可能的。因此,第一个要问的问题可能是,如果您选择可变模型,文档更新的频率可能是多少。如果订单的更新发生在每秒最多几次,请采用可变的想法并检查(可能很少发生)冲突。

    不可变模型最适合作为更新的替代方案,否则会在包含列表或对象的一些大型文档中发生 - 例如一组快速摄取的时间序列事件等。另一种方法是存储一组deltas,并从视图中获取这些 deltas 的全部集合并缝合回订单客户端。

    根据我从您的示例中了解到的情况,听起来您将相当于完整的新订单修订版本存储为新文档,而不是增量,基本上绕过了 Cloudant 自己的修订系统。这可能不太理想,但您也许可以找到一些方法。使用您的示例文档:

    function (doc) {
      emit([doc.order_id, doc.time], null);
    }
    

    要挑选最新版本的订单“1”,您可以发出如下查询:

    curl -s -g 'https://skruger.cloudant.com/demo2/_design/queries/_view/orders-by-time?startkey=[2]&endkey=[1]&include_docs=true&reduce=false&descending=true&limit=1'
    

    这给了

    {
      "total_rows": 4,
      "offset": 2,
      "rows": [
        {
          "id": "bfd5b38c482b04e45d35b6147adcc82a",
          "key": [
            1,
            3
          ],
          "value": null,
          "doc": {
            "_id": "bfd5b38c482b04e45d35b6147adcc82a",
            "_rev": "1-075a88a11bc842fa0def69556c81ab01",
            "order_id": 1,
            "details": "new",
            "time": 3
          }
        }
      ]
    }
    

    注意颠倒的开始键和结束键。上面的数据库是开放阅读,如果你想戳它。

    【讨论】:

    • 感谢@xpqz,我正在寻找列出系统中的所有订单(在一个数据库调用中)而不是特定订单。我的理解是您描述的方法不适用于所有订单。
    • 正确。对于完整列表,您需要聚合客户端。或者使用 raja 建议的 reducer。
    • 我想我必须做客户端聚合。分区数据库中实际上是否允许自定义减少功能?我问这个,因为我看到了这个:Design documents with options.partitioned set to true cannot contain custom JavaScript reduce functions, only built-in reduces are allowed. cloudant 中提到的doc
    • 啊,是的,正确——我错过了你在一个分区数据库上——没有 js 减少。这里的分区键是什么,order_id?
    • 是的,假设是order_id(我的实际系统模型不同,这里的例子只是代表它。)
    【解决方案2】:

    有一种取舍的方式,使用reduce 功能:

    地图功能:

    function (doc) {
      emit(doc.order_id, [doc.time, doc]);
    }
    

    减少功能:

    function (keys, values, rereduce) {
      var latest = [0, null];
      // I'm not familar with js, maybe you have a better way to find the max record
      values.forEach(function(value) {
        if (value[0] > latest[0]) {
          latest = value;
        }
      });
      return latest;
    }
    

    您可以获得以下文件:

    {"rows":[
    {"key":1,"value":[3,{"_id":"1bebc20edfa9839ee437feda170029f1","_rev":"2-b0209ac4ad56e751d75783e385c57cfb","order_id":1,"details":"new","time":3}]},
    {"key":2,"value":[4,{"_id":"1bebc20edfa9839ee437feda1700506e","_rev":"1-db68ad437bc41643ee1dca6435263075","order_id":2,"details":"new","time":4}]}
    ]}
    

    【讨论】:

    • 谢谢@raja。我将无法将其用于分区数据库,因为 Design documents with options.partitioned set to true cannot contain custom JavaScript reduce functions, only built-in reduces are allowed. (在 cloudant doc 中提到)
    猜你喜欢
    • 2022-12-09
    • 2019-07-29
    • 2021-06-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-19
    • 1970-01-01
    • 2020-05-27
    相关资源
    最近更新 更多