0

如果我有状态更新的 CouchDB:

{
  username: "JP",
  update: "Confused by CouchDB",
  updated_at: 2013-05-10T08:30:00Z
}

{
  username: "JP",
  update: "Blissfully unaware",
  updated_at: 2012-05-09T08:30:00Z
}

{
  username: "Bob",
  update: "Talking nonsense",
  updated_at: 2013-04-07T22:15:00Z
}

我想检索 JP 的最新更新。

  1. 我知道我可以创建一个这样的地图函数来选择所有 JP 的更新:

    function(doc) {
      emit(doc.username,doc);
    }
    

    然后查询_view/by_username?key="JP"- 但我必须自己对输出进行排序以找到具有最新日期的输出。

  2. 我知道我可以创建一个这样的地图函数来按日期和用户名排序:

    function(doc) {
      emit([doc.username, doc.updated_at],doc);
    }
    

    但是然后我需要知道更新的时间才能通过 JP 请求更新(据我所知,没有_view/by_username?key=["JP",*]类型请求可以匹配任何内容)

  3. 我尝试在上面的 (1) 之上使用 reduce 函数,如下所示:

    function (keys, values, rereduce) {
      var latest;
    
      for(var a in keys) {
          if (latest === undefined || new Date(values[a].updated_at).getTime() > new Date(latest.updated_at).getTime()) {
            latest = values[a];
          }
      }
    
      return latest;
    }
    

    但是因为我存储的文档实际上非常大,所以我得到了“减少不够快”的错误——我的 reduce 函数输出了大约一半的数据(即两个传入的文档变成一个传出的文档),这显然足以触发警告信息。

我觉得我在这里遗漏了一些东西 - 任何人都可以帮助我吗?

4

1 回答 1

0

我maaaay刚刚回答了我自己的问题。

当 reduce 函数的输出与输入相比较大时,就会发生错误。在具有奇数个文档的数据库上,必须在输入仅为单个文档的情况下进行归约 - 这当然需要输出与输入的大小相同:错误。

如果我将 (3) 中的 reduce 函数更改为仅发出文档 ID,则不会触发错误:

function (keys, values, rereduce) {
  var latest;

 for(var a in keys) {
      if (latest === undefined || new Date(values[a].updated_at).getTime() > new Date(latest.updated_at).getTime()) {
        latest = {"_id": values[a]._id};
      }
  }

  return latest;
}

但是您不能请求include_docs=true减少视图(尽管三年前#COUCHDB-914!),因此必须单独请求检索文档详细信息。这确实阻碍了我的用例,所以我仍在寻找更好的答案。

于 2013-05-10T08:58:28.093 回答