如何在CouchDB中编写SELECT COUNT(不同字段)查询?

如何在CouchDB中编写SELECT COUNT(不同字段)查询?,couchdb,Couchdb,在CouchDB中,有没有一种很好的方法来模拟SELECT COUNT(不同字段)的行为 假设我们有以下文档,其中记录了用户播放某首歌曲的时间: { song_id: "happy birthday", user_id: "boris", date_played: [2011, 11, 14, 00, 12, 55], _id: ... } 我想知道我们的用户“boris”曾经播放过多少首不同的歌曲。如果我们的用户已经听了20遍“生日快乐”,那么这首歌仍然只占歌曲总数的+1 在

在CouchDB中,有没有一种很好的方法来模拟SELECT COUNT(不同字段)的行为

假设我们有以下文档,其中记录了用户播放某首歌曲的时间:

{
  song_id: "happy birthday",
  user_id: "boris",
  date_played: [2011, 11, 14, 00, 12, 55],
  _id: ...
}
我想知道我们的用户“boris”曾经播放过多少首不同的歌曲。如果我们的用户已经听了20遍“生日快乐”,那么这首歌仍然只占歌曲总数的+1

在MySQL中,我只需从播放中执行
SELECT COUNT(DISTINCT song_id),其中user_id=“boris”
,但在CouchDB中编写这篇文章时,我是一片空白

解决方法1:如果我更改了模式,而是将所有歌曲播放内容存储在“boris”的单个用户文档中,那么我就可以编写一个映射,只发出不同的值。然而,如果我想在last.fm的规模上构建一些东西,我担心随着“boris”文档大小(播放次数)的持续增长,更新会花费很长时间。(可能还有一个我最终会达到的最大文档大小)

解决方法2:我还可以编写一个map函数来返回所有不同的记录,我的python脚本可以自己总结这些记录;但同样,对于成千上万首不同的歌曲,这也会变得非常缓慢


我还缺少什么选择?

假设我正确地解释了你的问题

地图:

减少:

_count
_approx_count_distinct
查询:

?startkey=[<userid>]&endkey=[<userid>,{}]&group=true

此答案由Zachary Zolton在couchdb邮件列表中提供:

既然你已经看到了Boris的五万张独一无二的照片 歌曲,您可以使用list函数返回行数

像这样的事情应该可以做到:

function() {
 var count = 0;
 while(getRow()) count++;
 return JSON.stringify({count: count});
}
如果查询此列表函数,请使用相同的视图、键范围和 在组级别,它将只响应一点JSON,例如:
{“count”:“50612”}

您可以在此处阅读更多内容:


我一直在为同样的事情挣扎(见)

当您只需要一个标量值时,获取所有这些输出是不对的。尽管list函数是一种解决方法,可以避免无法获得完整的结果流,但这种方法感觉非常奇怪


有其他方法吗?

在CouchDB(>2.2)的最新版本中,您可以使用reduce函数。你的看法是:

/db/_design/_myddoc/_view/myview?group_level=1&key=["boris"]
地图:

减少:

_count
_approx_count_distinct
获取用户“boris”的song_ID计数的查询是:

/db/_design/_myddoc/_view/myview?group_level=1&key=["boris"]

我还考虑将这些信息作为一个单独的文档来编写:检查(user_id,song_id)是否已经存在,如果已经存在,则更新时间戳,否则插入新文档。但我希望可以使用CouchDB的增量map/reduce更新来为我构建这个缓存。这个map/reduce会给你([“boris”,“生日快乐”],20),([“boris”,“昨天”],14),…),但是如果用户听了50000首不同的歌曲,那么这个查询将返回50000行不同的内容。基本上我想得到的只是标量值50000。