首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用MapReduce从CouchDB中提取一组文档id

如何使用MapReduce从CouchDB中提取一组文档id
EN

Stack Overflow用户
提问于 2014-03-22 10:00:08
回答 1查看 2K关注 0票数 4

我正在进行CouchDB实验的第一周,并试图停止使用SQL进行思考。我有一个文档集合(5000个事件文件),所有这些文档都有一些ID值,这些ID值对于文档组来说是通用的。所以可能有10个都有TheID:'foobar‘。

(如果有人问-- TheID不是关系数据库中的自动增量值,它是我们的合作伙伴分配的唯一id。我不能以其他方式重新设计我的源数据,我必须使用这个TheID字段来识别文档组。)

我想查询我的文件列表:

代码语言:javascript
复制
{ _id: 'document1', Message: { TheID: 'foobar' } }
{ _id: 'document2', Message: { TheID: 'xyz' } }
{ _id: 'document3', Message: { TheID: 'xyz' } }
{ _id: 'document4', Message: { TheID: 'foobar' } }
{ _id: 'document5', Message: { TheID: 'wibble' } }
{ _id: 'document6', Message: { TheID: 'foobar' } }

我想知道结果:

代码语言:javascript
复制
'foobar': [ 'document1', 'document4', 'document6' ]
'xyz': [ 'document2', 'document3' ]
'wibble': [ 'document5' ]

其目的是表示按TheID分组的UI上的文档组,这样用户就可以一起查看特定TheID的所有文档,并选择该TheID来钻取仅通过TheID值进行的数据查询。是的,每个文档的字符串id是有用的--在我们的示例中,每个文档的_id值是源事件标识符,因此它是用户希望在屏幕上的列表中看到的唯一和有用的值。

在SQL中,您可以按TheID字段排序或分组,并适当地迭代结果集。对于CouchDB查询,我怀疑这种想法是否有用。

我知道我可以使用一个map函数来提取每个文档的TheID值,例如:

代码语言:javascript
复制
function (doc) {
  emit(doc.Message.TheID, 1);
}

或者也许

代码语言:javascript
复制
function (doc) {
  emit(doc._id, doc.Message.TheID);
}

我不确定我应该发出什么作为关键和价值。即使这是有用的,我也觉得我不应该使用result函数来将大型地图输出(数据库中的每个文档都有一个结果行)“缩小”到我想要的(每个结果都有一个文档id列表)。

http://guide.couchdb.org/draft/views.html说:“新的CouchDB用户犯了一个常见的错误,就是试图用一个约简函数构造复杂的聚合值。完全缩减应该会产生一个标量值,比如5,而不是,例如,一个带有一组唯一键的JSON散列,以及每个键的计数。”

我想我可能可以使用reduce扫描映射的结果,并以某种方式将具有公共TheID值的所有结果收集到一个结果对象中。我在阅读reduce文档时看到的是,它将被赋予包含不可预测集合的键和值数组,这些集合由映射结果背后的btree结构驱动。它不会被赋予数组保证包含我可以扫描的所有类似的TheID值。这种方法似乎完全失败了。

那么,在这里做地图/缩减对是正确的吗?我应该用“秀”或“列表”来代替吗?我打算围绕结果构建一个基于胡子的HTML模板引擎,所以“列表”似乎是错误的。

提前感谢您的指导。

编辑我已经做了一些本地开发,并想出了一个我认为是坏的解决方案。希望这能告诉你我想要进入的方向。参见我在view/collectByTheID创建的基于公共云的view/collectByTheID

这是公开的。如果你想玩,请把它复制到一个新的视图,不要污染这个,以防其他人进来看原稿。

地图功能:

代码语言:javascript
复制
function(doc) {
  emit(doc.Message.TheID, doc._id);
}

减少功能:

代码语言:javascript
复制
function(keys, values, rereduce) {
  if (!rereduce) {
    return values;
  } else {
    var ret = [];
    values.forEach(function (ar) {
      ret.concat(ar);
    });
    return ret;
  }
}

结果:

代码语言:javascript
复制
"foobar"   ["document6", "document4", "document1"]
"wibble"   ["document5"]
"xyz"      ["document3", "document2"]

减值函数首先将值数组单独保留,然后在第二次传递时将它们连接在一起。但是,当我在我的大型5000+文档数据库上运行它时,它会得到一些带有空文档id数组的TheID值。我相信这会受到我前面提到的问题的困扰,在这个问题中,传递给减缩的值数组依赖于它们提取的映射的btree结构,并且不能保证包含给定键的完整值集。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-03-24 15:12:40

利用group_level特性:

映射:

代码语言:javascript
复制
emit([doc.message.TheID, doc._id], null)

减少:

您必须包括使用group_level的减缩,它可以是空的,如下面或其他什么东西,即_count

代码语言:javascript
复制
function(keys, values){
   return null;
}

使用group_level=1的查询将返回:

代码语言:javascript
复制
/_design/d/_view/v?group_level=1

[
 {key: ["foobar"], value: null}, 
 {key: ["xyz"], value: null}, 
 {key: ["wibble"], value: null}
]

您将使用此查询填充分组UI中的顶层。当用户展开一个类别时,您将使用group_level 2和start和end键执行另一个查询:

代码语言:javascript
复制
/_design/d/_view/v?group_level=2&startkey=["foobar"]&endkey=["foobar",{}]

[
  {key: ["foobar", "document6"], value: null}, 
  {key: ["foobar", "document4"], value: null}, 
  {key: ["foobar", "document1"], value: null}
]

这不能完全按照您的要求生成输出,但是,我认为您会发现它足够灵活

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/22576092

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档