Couchdb 如果文档具有特定密钥,如何获取重复数据消除的文档列表(在时间戳-最新wins上)?

Couchdb 如果文档具有特定密钥,如何获取重复数据消除的文档列表(在时间戳-最新wins上)?,couchdb,cloudant,Couchdb,Cloudant,我想在cloudant分区数据库(如上所述)中使用只写(不可变)文档策略,其中对于每个文档更新,我都会创建一个带有更新字段的新文档。例如:db由订单组成(包含订单id、详细信息、创建文档的时间)。假设某个订单的详细信息需要更新-我使用更新的数据创建了一个新文档,并保留了订单id。现在,我希望在某个时间点查看系统中的所有订单,如果有订单id相同的文档,则列表中只应显示最新日期的文档 我能想到的唯一方法是从数据库中提取所有文档,然后在客户端自己进行过滤,但是我是否可以在数据库中使用某些东西来获得这样

我想在cloudant分区数据库(如上所述)中使用只写(不可变)文档策略,其中对于每个文档更新,我都会创建一个带有更新字段的新文档。例如:db由订单组成(包含订单id、详细信息、创建文档的时间)。假设某个订单的详细信息需要更新-我使用更新的数据创建了一个新文档,并保留了订单id。现在,我希望在某个时间点查看系统中的所有订单,如果有订单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"
}

有一种折衷方法,使用
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;
}
减少功能:

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}]}
]}

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

不可变模型最适合作为更新的替代方案,否则更新将发生在包含列表或对象的几个大型文档中,如一组快速接收的时间序列事件等。另一种方法是存储一组增量,并从视图中获取这些增量的完整集,然后在客户端缝合订单

根据我从您的示例中了解到的情况,听起来您将订单的完整、新修订内容存储为新文档,而不是增量,基本上绕过了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,我想列出系统中的所有订单(在一个db调用中),而不是特定的订单。我的理解是,你所描述的方法不适用于所有订单。正确。要获得完整列表,您需要聚合客户端。或者使用raja建议的reducer。我想我必须进行客户端聚合。分区数据库中是否允许自定义reduce功能?我问这个问题,因为我看到了:
designdocuments with options.partitioned设置为true不能包含自定义JavaScript reduce函数,只允许内置reduce啊,是的,没错——我错过了你在一个分区数据库上——没有。这里的分区键是什么,order_id?是的,让我们假设它是order_id(我的实际系统模型不同,这里的示例只是它的代表。)谢谢@raja。对于分区数据库,我将无法使用此选项,因为
Design documents with options.partitioned设置为true不能包含自定义JavaScript reduce函数,只允许使用内置reduce(在cloudant中提到)