在CouchDB中按键返回唯一值

way*_*ind 8 couchdb mapreduce

有没有办法在CouchDB中执行以下操作?一种通过给定键返回唯一,不同值的方法?

SELECT DISTINCT field FROM table WHERE key="key1"

'key1' => 'somevalue'
'key1' => 'somevalue'
'key2' => 'anotherval'
'key2' => 'andanother'
'key2' => 'andanother'
Run Code Online (Sandbox Code Playgroud)

例如:

http:// localhost:5984/database/_design/designdoc/_view/distinctview?key = "key1"将返回['somevalue']

http:// localhost:5984/database/_design/designdoc/_view/distinctview?key = "key2"将返回['anotherval','andanother']

Mar*_*cio 9

正如CouchDB权威指南中所建议的那样,您应该在键中放置您想要唯一的值,然后使用查询reduce函数group=true.

例如,如果keyfield是带有"key1"和"key2" valuefield的字段并且是带有值的字段,则您的map函数可以是:

function(doc) {
  // filter to get only the interesting documents: change as needed
  if (doc.keyfield && doc.valuefield) {
    /*
     * This is the important stuff:
     * 
     *  - by putting both, the key and the value, in the emitted key,
     *    you can filter out duplicates
     *    (simply group the results on the full key);
     * 
     *  - as a bonus, by emitting 1 as the value, you get the number
     *    of duplicates by using the `_sum` reduce function.
     */
    emit([doc.keyfield, doc.valuefield], 1);
  }
}
Run Code Online (Sandbox Code Playgroud)

你的reduce函数可能是:

_sum
Run Code Online (Sandbox Code Playgroud)

然后查询group=true&startkey=["key2"]&endkey=["key2",{}]给出:

{"rows":[
{"key":["key2","anotherval"],"value":1},
{"key":["key2","andanother"],"value":2}
]}
Run Code Online (Sandbox Code Playgroud)


Dom*_*nes 3

根据我在这里看到的内容(如果需要,我会更改我的答案)key1并且key2看起来像独立的字段,因此您需要 2 个单独的视图。

我在测试数据库中创建了 5 个简单文档:

// I've left out fields like _id and _rev for the sake of simplicity
{ "key1": "somevalue" }
{ "key1": "somevalue" }
{ "key2": "anotherval" }
{ "key2": "andanother" }
{ "key2": "andanother" }
Run Code Online (Sandbox Code Playgroud)

以下是您需要的 2 个视图查询:

// view for key1
function(doc) {
  if (doc.key1) {
    emit("key1", doc.key1);
  }
}

// view for key2
function(doc) {
  if (doc.key2) {
    emit("key2", doc.key2);
  }
}
Run Code Online (Sandbox Code Playgroud)

从那里,您的reduce函数只需执行以下操作即可返回数组中的所有值:

function (key, values) {
  return values;
}
Run Code Online (Sandbox Code Playgroud)

但是,您特别提到了不同的价值观。由于 JavaScript 没有unique()数组的本机方法,并且我们无法在视图函数中使用 CommonJS 模块,因此我们必须为此添加自己的逻辑。我刚刚复制粘贴了array.unique()我在 Google 上找到的第一个函数,您可以编写自己的函数,这肯定会得到更好的优化。

function (key, values, rereduce) {
  var o = {}, i, l = values.length, r = [];

  for (i = 0; i < l; i += 1) {
    o[values[i]] = values[i];
  }

  for (i in o) {
    r.push(o[i]);
  }

  return r;
}
Run Code Online (Sandbox Code Playgroud)

您将在两个视图中使用相同的归约函数。当您查询任何这些视图时,默认情况下它也会执行reduce。(您需要显式传递reduce=false才能获取函数的结果map

以下是您使用上述查询检索的结果集map/reduce:(请记住它们是 2 个单独的查询)

{"rows":[
  {"key":"key1", "value": ["somevalue"]}
]}

{"rows":[
  {"key": "key2", "value": ["anotherval", "andanother"]}
]}
Run Code Online (Sandbox Code Playgroud)