减少 CouchDB 中的多个字段值
Reduce multiple field values in CouchDB
对于通知系统,我将用户消息存储在 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
}
字段 status 可以有两个值 new
或 read
- 我正在尝试将 Map/Reduce 视图写入 return 某个用户的计数,包括他们有多少条状态为 new
的消息以及有多少条状态为 read
.
映射函数非常简单:
function(doc) {
emit(doc.uid, doc.status);
}
它 return 是这样的:
| key | value
+------------------------------------+------------------------------
| bc325c2f6a99194ecab6e7bbae80eb29 | "read"
+------------------------------------+------------------------------
| bc325c2f6a99194ecab6e7bbae80eb29 | "read"
+------------------------------------+------------------------------
| bc325c2f6a99194ecab6e7bbae80eb29 | "read"
+------------------------------------+------------------------------
| bc325c2f6a99194ecab6e7bbae80eb29 | "new"
+------------------------------------+------------------------------
| bc325c2f6a99194ecab6e7bbae80eb29 | "new"
我现在正在尝试弄清楚如何编写一个会产生此结果的 reduce 函数:
| 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)
但它 returns null
.
我似乎无法解决这个问题。任何人都可以让我走上正轨吗?
我找到了一种方法,但我不确定这是否是正确的方法:
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}
+------------------------------------+------------------------------
我的建议是发出 uid
和 status
作为您的密钥,然后您将获得作为减少值的计数。
首先,我们将从地图功能开始:
function (doc) {
emit([ doc.uid, doc.status ]);
}
请注意,我们只发出一个键,而不是一个值。 (事实证明在这种情况下我们不需要它)
然后,使用下面的built-in reduce function
_count
您的视图输出将包含如下键:(记住,我们不关心值)
[ "bc325c2f6a99194ecab6e7bbae80eb29", "read" ]
[ "bc325c2f6a99194ecab6e7bbae80eb29", "read" ]
[ "bc325c2f6a99194ecab6e7bbae80eb29", "read" ]
[ "bc325c2f6a99194ecab6e7bbae80eb29", "new" ]
[ "bc325c2f6a99194ecab6e7bbae80eb29", "new" ]
查询视图时,确保包含 group=true
(隐含 reduce=true
)
您会注意到您的视图现在有以下 key/value 对:
[ "bc325c2f6a99194ecab6e7bbae80eb29", "read" ]: 3
[ "bc325c2f6a99194ecab6e7bbae80eb29", "new" ]: 2
如果您的数据库中有更多文档,您也会看到所有其他用户 ID。要过滤到您关心的用户,只需使用:
startkey=["bc325c2f6a99194ecab6e7bbae80eb29"]
endkey=["bc325c2f6a99194ecab6e7bbae80eb29",{}]
这些数组看起来有点奇怪,我敢肯定,但它们只是确保匹配 "status" 的任何值。 (查看 Views Collation 上的文档了解更多信息)
这种方法可以很好地扩展,允许任何其他 status
值在没有任何代码更改的情况下工作。
对于通知系统,我将用户消息存储在 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
}
字段 status 可以有两个值 new
或 read
- 我正在尝试将 Map/Reduce 视图写入 return 某个用户的计数,包括他们有多少条状态为 new
的消息以及有多少条状态为 read
.
映射函数非常简单:
function(doc) {
emit(doc.uid, doc.status);
}
它 return 是这样的:
| key | value
+------------------------------------+------------------------------
| bc325c2f6a99194ecab6e7bbae80eb29 | "read"
+------------------------------------+------------------------------
| bc325c2f6a99194ecab6e7bbae80eb29 | "read"
+------------------------------------+------------------------------
| bc325c2f6a99194ecab6e7bbae80eb29 | "read"
+------------------------------------+------------------------------
| bc325c2f6a99194ecab6e7bbae80eb29 | "new"
+------------------------------------+------------------------------
| bc325c2f6a99194ecab6e7bbae80eb29 | "new"
我现在正在尝试弄清楚如何编写一个会产生此结果的 reduce 函数:
| 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)
但它 returns null
.
我似乎无法解决这个问题。任何人都可以让我走上正轨吗?
我找到了一种方法,但我不确定这是否是正确的方法:
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}
+------------------------------------+------------------------------
我的建议是发出 uid
和 status
作为您的密钥,然后您将获得作为减少值的计数。
首先,我们将从地图功能开始:
function (doc) {
emit([ doc.uid, doc.status ]);
}
请注意,我们只发出一个键,而不是一个值。 (事实证明在这种情况下我们不需要它)
然后,使用下面的built-in reduce function
_count
您的视图输出将包含如下键:(记住,我们不关心值)
[ "bc325c2f6a99194ecab6e7bbae80eb29", "read" ]
[ "bc325c2f6a99194ecab6e7bbae80eb29", "read" ]
[ "bc325c2f6a99194ecab6e7bbae80eb29", "read" ]
[ "bc325c2f6a99194ecab6e7bbae80eb29", "new" ]
[ "bc325c2f6a99194ecab6e7bbae80eb29", "new" ]
查询视图时,确保包含 group=true
(隐含 reduce=true
)
您会注意到您的视图现在有以下 key/value 对:
[ "bc325c2f6a99194ecab6e7bbae80eb29", "read" ]: 3
[ "bc325c2f6a99194ecab6e7bbae80eb29", "new" ]: 2
如果您的数据库中有更多文档,您也会看到所有其他用户 ID。要过滤到您关心的用户,只需使用:
startkey=["bc325c2f6a99194ecab6e7bbae80eb29"]
endkey=["bc325c2f6a99194ecab6e7bbae80eb29",{}]
这些数组看起来有点奇怪,我敢肯定,但它们只是确保匹配 "status" 的任何值。 (查看 Views Collation 上的文档了解更多信息)
这种方法可以很好地扩展,允许任何其他 status
值在没有任何代码更改的情况下工作。