javascript - Map-Reduce 查询以计数标签

标签 javascript couchdb mapreduce

我有一个用关键字标记的文档数据库。我试图找到(然后计算)彼此一起使用的唯一标签。因此,对于任何给定的标签,我想知道与该标签一起使用了哪些标签。

例如,如果我有一个包含标签 [fruit, apple, plant] 的文档,那么当我查询 [apple] 时,我应该得到 [水果、植物]。如果另一个文档有标签 [apple, banana],那么我对 [apple] 的查询会给我 [fruit, plant, banana]

这是我的 map 函数,它发出所有标签及其邻居:

function(doc) {
  if(doc.tags) {
    doc.tags.forEach(function(tag1) {
      doc.tags.forEach(function(tag2) {
        emit(tag1, tag2);
      });
    });
  }
}

所以在我上面的例子中,它会发出

apple -- fruit
apple -- plant
apple -- banana
fruit -- apple
fruit -- plant
...

我的问题是:我的 reduce 函数应该是什么? reduce 函数应该基本上过滤掉重复项并将它们组合在一起。

我尝试了很多不同的尝试,但我的数据库服务器 (CouchDB) 一直给我一个错误:reduce_overflow_error。减少产量必须收缩得更快


编辑:我发现了一些似乎有效的东西,但我不确定为什么。我看到 reduce 函数调用有一个可选的“rereduce”参数。如果我忽略这些特殊情况,它就会停止抛出 reduce_overflow_errors。谁能解释为什么?而且,我是否应该忽略这些,否则这会在以后咬我的屁股吗?

function(keys, values, rereduce) {
  if(rereduce) return null; // Throws error without this.

  var a = [];
  values.forEach(function(tag) {
    if(a.indexOf(tag) < 0) a.push(tag);
  });
  return a;
}

最佳答案

您的回答很好,正如我在评论中所说,如果它对您有用,那么您应该关心的就是这些。如果您遇到性能问题,这里有一个替代实现。

CouchDB 喜欢长列表,而不是长列表。此解决方案不是将 View 行与以前看到的每个标签保持一个数组,而是将“兄弟”标签保留在 View 行的 key 中,然后是 group them together保证每行有一个唯一的兄弟标签。每行只有两个标签,但可能有数千或数百万行:一个长列表,CouchDB 更喜欢这种列表。

主要思想是发出一个 2 数组的标签对。假设我们有一个文档,标记为 fruit, apple, plant

// Pseudo-code visualization of view rows (before reduce)
// Key         , Value
[apple, fruit ], 1
[apple, plant ], 1 // Basically this is every combination of 2 tags in the set.
[fruit, apple ], 1
[fruit, plant ], 1
[plant, apple ], 1
[plant, fruit ], 1

接下来我标记一些东西 apple, banana

// Pseudo-code visualization of view rows (before reduce)
// Key         , Value
[apple, banana], 1 // This is from my new doc
[apple, fruit ], 1
[apple, plant ], 1 // This is also from my new doc
[banana, apple], 1
[fruit, apple ], 1
[fruit, plant ], 1
[plant, apple ], 1
[plant, fruit ], 1

为什么值总是1?因为我可以做一个非常简单的内置 reduce 函数:_sum 来告诉我所有标签对的计数。接下来,使用 ?group_level=2 进行查询,CouchDB 将为您提供唯一的对,以及它们的总数。

生成这种 View 的 map 函数可能如下所示:

function(doc) {
  // Emit "sibling" tags, keyed on tag pairs.
  var tags = doc.tags || []
  tags.forEach(function(tag1) {
    tags.forEach(function(tag2) {
      if(tag1 != tag2)
        emit([tag1, tag2], 1)
    })
  })
}

关于javascript - Map-Reduce 查询以计数标签,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10410030/

相关文章:

javascript - Zurb-Foundation 6/Abide 自定义验证模式如何工作?

javascript - 亚马逊土耳其机器人 : How to use react/redux to implement HIT?

python - 在Python中使用json解析couchdb查询结果

mapreduce - Couch DB - 传递输入参数以查看

hadoop - 在hadoop中保存和访问类似表的数据结构

javascript - 创建自定义滚动事件,与用户事件区分开来?

javascript - Node.js SSL 错误 - 没有可用的密码

grails - 哪个框架用于访问 couchDB 的门户网站?

ssl - 如何在 Ubuntu 上运行的 CouchDB 上启用 SSL?

java - Java MapReduce按日期计数