对于通知系统,我将用户消息存储在CouchDB中。我的文档结构看起来像这样:
{
"_id": "bc325c2f6a99194ecab6e7bbae81b609",
"_rev": "1-9745ddb21cefe3dbc8cc1f7f7bd8d11d",
"uid": "bc325c2f6a99194ecab6e7bbae80eb29",
"msg": "Hi there, here is a message for you!",
"level": "warning",
"status": "new",
"created": 1467180077,
"read": null
}
字段状态可以有两个值new
或read
-我试图编写一个Map/Reduce视图,以返回特定用户的计数,其中有多少消息具有状态new
和状态read
。
Map函数非常简单:
function(doc) {
emit(doc.uid, doc.status);
}
返回如下内容:
| key | value
+------------------------------------+------------------------------
| bc325c2f6a99194ecab6e7bbae80eb29 | "read"
+------------------------------------+------------------------------
| bc325c2f6a99194ecab6e7bbae80eb29 | "read"
+------------------------------------+------------------------------
| bc325c2f6a99194ecab6e7bbae80eb29 | "read"
+------------------------------------+------------------------------
| bc325c2f6a99194ecab6e7bbae80eb29 | "new"
+------------------------------------+------------------------------
| bc325c2f6a99194ecab6e7bbae80eb29 | "new"
我现在正试图找出如何写一个减少函数,将产生这个:
| key | value
+------------------------------------+------------------------------
| bc325c2f6a99194ecab6e7bbae80eb29 | ["read":3, "new":2]
+------------------------------------+------------------------------
如果我使用这个reduce函数
function (key, values, rereduce) {
return values;
}
我:
| key | value
+------------------------------------+------------------------------
| bc325c2f6a99194ecab6e7bbae80eb29 | ["read","read","read","new","new"]
+------------------------------------+------------------------------
我尝试使用return count(values)
,但它返回null
。
我似乎不知道该如何处理这件事。有谁能给我指路吗?
我的建议是发出uid
和status
作为您的密钥,然后您将获得计数作为您的减少值。
function (doc) {
emit([ doc.uid, doc.status ]);
}
注意,我们只发出一个键,而不关心一个值。(在这种情况下我们不需要它)
然后,使用以下内置的reduce函数
_count
您的视图输出将包含如下键:(记住,我们不关心值)
-
[ "bc325c2f6a99194ecab6e7bbae80eb29", "read" ]
-
[ "bc325c2f6a99194ecab6e7bbae80eb29", "read" ]
-
[ "bc325c2f6a99194ecab6e7bbae80eb29", "read" ]
-
[ "bc325c2f6a99194ecab6e7bbae80eb29", "new" ]
-
[ "bc325c2f6a99194ecab6e7bbae80eb29", "new" ]
当您查询视图时,确保包含group=true
(隐含的reduce=true
)
你会注意到你的视图现在有以下键/值对:
-
[ "bc325c2f6a99194ecab6e7bbae80eb29", "read" ]: 3
-
[ "bc325c2f6a99194ecab6e7bbae80eb29", "new" ]: 2
如果您的数据库中有更多的文档,那么您也将看到所有其他用户id。要过滤到您关心的用户,只需使用:
-
startkey=["bc325c2f6a99194ecab6e7bbae80eb29"]
-
endkey=["bc325c2f6a99194ecab6e7bbae80eb29",{}]
这些数组看起来有点奇怪,我敢肯定,但这些只是确保"状态"的任何值都将被匹配。(查看view Collation的文档获取更多信息)
这种方法可以很好地扩展,允许任何其他status
值工作而无需任何代码更改。
我找到了这样做的方法,但我不确定这是否是正确的方法:
reduce函数:
function (key, values, rereduce) {
var result = new Object;
result.read = 0;
result.new = 0;
for(var i = 0; i < values.length; ++i){
if(values[i] == 'new'){
result.new++;
}
if(values[i] == 'read'){
result.read++;
}
};
return result;
}
将产生如下结果:
| key | value
+------------------------------------+------------------------------
| bc325c2f6a99194ecab6e7bbae80eb29 | {read: 2, new: 1}
+------------------------------------+------------------------------