如何编写基于时间戳的 map/reduce 视图以避免 CouchDB 中的更新?
How can I write a timestamp-based map/reduce view to avoid updates in CouchDB?
我正在尝试 "avoid updates" 在 CouchDB 中,这似乎是推荐的。
但是我无法使 "reduce" 视图 returns 只有最新值。在下面的数据集中,文档 a8f2298e5961b0ebf60e56022d253d2b
(其中 s=FooQuux)基本上应该永远不会返回,并且可以作为 "cleanup" 操作删除而不会影响。
我希望能够进行如下操作:
- 检索
a
的值 ==> Bar
- this technique 可以工作,使用
s
视图,搜索 [["a"], ["a",{}]]
with limit=1.
- 检索所有值 ==>
a=Bar, b=Quux
- 我可以将 reduce 写入 "strip out" 具有较旧时间戳的文档吗?
对于最后两个,考虑到限制,我不确定是否可以编写一个 map/reduce 视图来同时执行这两项操作。
- 获取每个用户的字符串长度 - group=1 ==
a=3, b=4
(不包括 FooQuux)
- 获取所有用户的字符串长度 - group=None ==
7
(不包括 FooQuux)
数据:(这是一个人为的例子)
给定数据:(其中 t 是时间戳,u 是用户名,s 是字符串)
- 在时间戳 0,用户
a
设置值 FooQuux
- 在时间戳 1,用户
a
设置值 Bar
- 在时间戳 2,用户
b
设置值 Quux
数据库:
{
"_id": "_design/all",
"views": {
"s": {
"map": "function(doc) { if(doc.u) { emit([doc.u, doc.s, doc.t], doc.s); } }"
},
"slen": {
"map": "function(doc) { if(doc.u) { emit([doc.u, doc.s, doc.t], doc.s.length); } }",
"reduce": "_sum"
}
},
"language": "javascript"
}
{
"_id": "a8f2298e5961b0ebf60e56022d251ebd",
"t": 2,
"u": "b",
"s": "Quux"
}
{
"_id": "a8f2298e5961b0ebf60e56022d253a1b",
"t": 1,
"u": "a",
"s": "Bar"
}
{
"_id": "a8f2298e5961b0ebf60e56022d253d2b",
"t": 0,
"u": "a",
"s": "FooQuux"
}
通过像这样创建一个 Map 函数:
function(doc) {
emit([doc.u, doc.t], doc.s);
}
您可以通过两种方式使用视图:
- 聚合数据 - 获取 u 值的文档数量计数(使用 _count reducer 和
?group_level=1
)
- 到 select 值为
u
- (reduce=false&endkey=["a"]&startkey=["az"]&descending=true&limit1
) 的最新记录
由于在索引过程中文档是单独处理的,因此不可能执行需要您了解另一个文档内容的逻辑。也就是说,您可以阻止文档在索引时被索引,if(doc.live){ emit(doc.u,null)}
但您不能执行 "cross-document" 逻辑。
不想pull a LEGO但这里有一个可能的解决方案:
地图
每个@Glynn-Bird 在
function(doc) {
emit([doc.u, doc.t], doc.s);
}
减少
function(keys, values, rereduce){
function rollin(map, u, o) {
if((!map[u]) || (o.t > map[u].t)) {
return o;
} else {
return map[u];
}
return map;
}
var m = {};
for(var i=0;i<values.length;i++) {
var v = values[i];
if(rereduce) {
// merge in this chunk
for(var u in v) {
m[u] = rollin(m, u, v[u]);
}
} else {
// roll in single entries
m[keys[i][0][0]] = rollin(m, keys[i][0][0], {
s: v,
t: keys[i][0][1],
});
}
}
return m;
}
输出
reduce=false
,startkey["a",{}]
endkey["a"]
,降序,limit 1
这是给"selecting a single specified entry"
的
{
"value": "Bar",
"key": [
"a",
1
],
"id": "a8f2298e5961b0ebf60e56022d253a1b"
}
减少,组级别 1
这是用于列表"specific values"(通过查询选择)
{
"value": {
"b": {
"s": "Quux",
"t": 2
}
},
"key": [
"b"
]
}
{
"value": {
"a": {
"s": "Bar",
"t": 1
}
},
"key": [
"a"
]
}
减少,组级别None
这是为了倾倒所有物品。
{
"value": {
"a": {
"s": "Bar",
"t": 1
},
"b": {
"s": "Quux",
"t": 2
}
},
"key": null
}
我正在尝试 "avoid updates" 在 CouchDB 中,这似乎是推荐的。
但是我无法使 "reduce" 视图 returns 只有最新值。在下面的数据集中,文档 a8f2298e5961b0ebf60e56022d253d2b
(其中 s=FooQuux)基本上应该永远不会返回,并且可以作为 "cleanup" 操作删除而不会影响。
我希望能够进行如下操作:
- 检索
a
的值 ==>Bar
- this technique 可以工作,使用
s
视图,搜索[["a"], ["a",{}]]
with limit=1.
- this technique 可以工作,使用
- 检索所有值 ==>
a=Bar, b=Quux
- 我可以将 reduce 写入 "strip out" 具有较旧时间戳的文档吗?
对于最后两个,考虑到限制,我不确定是否可以编写一个 map/reduce 视图来同时执行这两项操作。
- 获取每个用户的字符串长度 - group=1 ==
a=3, b=4
(不包括 FooQuux) - 获取所有用户的字符串长度 - group=None ==
7
(不包括 FooQuux)
数据:(这是一个人为的例子)
给定数据:(其中 t 是时间戳,u 是用户名,s 是字符串)
- 在时间戳 0,用户
a
设置值FooQuux
- 在时间戳 1,用户
a
设置值Bar
- 在时间戳 2,用户
b
设置值Quux
数据库:
{
"_id": "_design/all",
"views": {
"s": {
"map": "function(doc) { if(doc.u) { emit([doc.u, doc.s, doc.t], doc.s); } }"
},
"slen": {
"map": "function(doc) { if(doc.u) { emit([doc.u, doc.s, doc.t], doc.s.length); } }",
"reduce": "_sum"
}
},
"language": "javascript"
}
{
"_id": "a8f2298e5961b0ebf60e56022d251ebd",
"t": 2,
"u": "b",
"s": "Quux"
}
{
"_id": "a8f2298e5961b0ebf60e56022d253a1b",
"t": 1,
"u": "a",
"s": "Bar"
}
{
"_id": "a8f2298e5961b0ebf60e56022d253d2b",
"t": 0,
"u": "a",
"s": "FooQuux"
}
通过像这样创建一个 Map 函数:
function(doc) {
emit([doc.u, doc.t], doc.s);
}
您可以通过两种方式使用视图:
- 聚合数据 - 获取 u 值的文档数量计数(使用 _count reducer 和
?group_level=1
) - 到 select 值为
u
- (reduce=false&endkey=["a"]&startkey=["az"]&descending=true&limit1
) 的最新记录
由于在索引过程中文档是单独处理的,因此不可能执行需要您了解另一个文档内容的逻辑。也就是说,您可以阻止文档在索引时被索引,if(doc.live){ emit(doc.u,null)}
但您不能执行 "cross-document" 逻辑。
不想pull a LEGO但这里有一个可能的解决方案:
地图
每个@Glynn-Bird 在
function(doc) {
emit([doc.u, doc.t], doc.s);
}
减少
function(keys, values, rereduce){
function rollin(map, u, o) {
if((!map[u]) || (o.t > map[u].t)) {
return o;
} else {
return map[u];
}
return map;
}
var m = {};
for(var i=0;i<values.length;i++) {
var v = values[i];
if(rereduce) {
// merge in this chunk
for(var u in v) {
m[u] = rollin(m, u, v[u]);
}
} else {
// roll in single entries
m[keys[i][0][0]] = rollin(m, keys[i][0][0], {
s: v,
t: keys[i][0][1],
});
}
}
return m;
}
输出
reduce=false
,startkey["a",{}]
endkey["a"]
,降序,limit 1
这是给"selecting a single specified entry"
的{
"value": "Bar",
"key": [
"a",
1
],
"id": "a8f2298e5961b0ebf60e56022d253a1b"
}
减少,组级别 1
这是用于列表"specific values"(通过查询选择)
{
"value": {
"b": {
"s": "Quux",
"t": 2
}
},
"key": [
"b"
]
}
{
"value": {
"a": {
"s": "Bar",
"t": 1
}
},
"key": [
"a"
]
}
减少,组级别None
这是为了倾倒所有物品。
{
"value": {
"a": {
"s": "Bar",
"t": 1
},
"b": {
"s": "Quux",
"t": 2
}
},
"key": null
}