CouchDB 视图(map/reduce)

Posted

技术标签:

【中文标题】CouchDB 视图(map/reduce)【英文标题】:CouchDB Views (map/reduce) 【发布时间】:2016-07-17 14:45:26 【问题描述】:

我在 CouchDB 1.6.1 中有类似的文档:

 "_id": "test_test",
 "_rev": "4-8eb22214f7f3dccd3c979f95ded0a7b0",
 "test": 
   "sample": 
       "abc": 
           "aaa": 877,
           "bbb": 202,
           "ccc": 0,
           "ddd": 362,
           "eee": 242,
           "ggg": 81
       ,
       "def": 
           "aaa": 697,
           "bbb": 233,
           "ccc": 0,
           "ddd": 178,
           "eee": 90,
           "ggg": 5
       ,
       "ghi": 
           "aaa": 987,
           "bbb": 396,
           "ccc": 0,
           "ddd": 399,
           "eee": 178,
           "ggg": 108
       ,
       "jkl": 
           "aaa": 1165,
           "bbb": 332,
           "ccc": 0,
           "ddd": 286,
           "eee": 173,
           "ggg": 100
       ,

我希望从中提取数据,例如:

1)

"test": 
"sample": 
   "abc": 
       "aaa": 877,
   "def": 
       "aaa": 697,
   "ghi": 
       "aaa": 987, etc.

或:

2)
"test": 
"sample": 
   "def": 
       "aaa": 697,
       "bbb": 233,
       "ccc": 0,
       "ddd": 178,
       "eee": 90,
       "ggg": 5
   ,

我还希望能够获得所有带有'test' 的文档或所有带有'sample' 的文档或所有带有'def' 的文档或所有带有'aaa' 的文档的总数。

我有一个地图javascript如下:

function(doc) 
if(doc.test.sample.abc.aaa)
emit(null, doc.test.sample.abc.aaa);


这正确地给出了一个值 (877)

我也试过了

function(doc) 
for (var i in doc.test.sample.abc)
emit(doc.test.sample.abc[i], null);


希望得到:

 "aaa": 877,
 "bbb": 202,
 "ccc": 0,
 "ddd": 362,
 "eee": 242,
 "ggg": 81

有时使用 map/reduce 可以成功,但有时没有任何效果。

遍历字段似乎很困难。

任何帮助将不胜感激。

编辑

CouchDB The Definitive Guide 的“更改通知、过滤器”部分的示例代码


"_id": "_design/app",
"_rev": "1-b20db05077a51944afd11dcb3a6f18f1",
"filters": 
"important": "function(doc, req)  if(doc.priority == 'high')  return true; 
else  return false; "


如果我将此代码粘贴到 CouchDB 中,它会被拒绝。 它也未能通过 JSONLint 测试。 我试过用相同的结果缩小它。 我在这里没有看到什么? 下面“答案 2”中引用的代码通过 JSONLint 测试并且 CouchDB 接受它。 但是,一旦开始进入特定功能,事情就会出错。 请问有没有办法解决这个问题。 再次感谢。

编辑2

我快到了??

此代码已被 Couch 接受:


"_id": "_design/lists",
"_rev": "3-628dc2f53051971994043c2e0bfc44ea",
"language": "javascript",
"views": 
   "list_setup": 
       "map": "function(doc) if(doc.compartment.number)  emit(null,   doc.compartment.number);"
   
,
"lists": 
   "first_list": "function(head, req) var result = []; while (row = getRow())  if (row !== null)   row.key  + row.value  else send(JSON.stringify(status_code: 404));send(JSON.stringify(result));"


但是,如果我运行 curl,我会得到 ​​p>

"error":"compilation_error","reason":"Expression does not eval to a function. (function(head, req) var result = []; while (row = getRow())  if (row !== null)   row.key  + row.value  else send(JSON.stringify(status_code: 404));send(JSON.stringify(result));)"

我不确定如何处理函数的 row.key + row.value 部分。

抱歉,拖了这么久。

【问题讨论】:

你能澄清我的问题吗?您需要有关 test.sample.abc childs 上的映射功能的帮助吗? Alexis Côté 我需要帮助,例如获取上述选项 1)。 【参考方案1】:

要完成您的第一个选项,您可以结合使用地图和列表功能。

使用地图功能,您可以为所有文档创建索引

function(doc)
  emit(null, doc._id);

如果您想更具体地查询您的视图,则必须发出此特定值。

下一部分是列表函数。如果您使用“include_docs=true”查询您的视图,您将获得整个文档。在此基础上,您可以使用列表函数来格式化“预”结果。 map 函数的每个结果都位于一个包含对象的数组中(每个对象都是 相当于一个文件)。

这是我的列表函数模式:

function(head, req) 
   var result = [];

   while (row = getRow()) 
      if (row !== null) 
         // make your formatting here
      else
         send(JSON.stringify(
            status_code: 404
         ));
      
   

   send(JSON.stringify(result));

最终查询如下所示

curl -X GET -g 'http://[host]:[port]/[db]/_design/[ddoc name]/_list/[list func name]/[map func name]?[query]&include_docs=true'

作为参考,这里官方文档:http://docs.couchdb.org/en/1.6.1/api/ddoc/render.html#db-design-design-doc-list-list-name-view-name

【讨论】:

其实并不难理解。不要害怕我的列表函数模式。首先,我建议使用 JavaScript 来了解 JSON 格式。为了更好地理解,一方面是您的初始文档,另一方面是您真正想要的。之后看看如何使用 JavaScript 格式化所有内容。作为提示,JavaScript 中的 JSON 文档只是对象和数组。所以你只需要重新排列你的文件。如果你有,把你的代码放在我的列表函数模式中。 json.orgeloquentjavascript.net/1st_edition/chapter4.html 基本上我不知道如何在蒲团中进行设置。各种网站和你的参考都很好的解释,但我不知道在哪里插入列表代码。我设置了一个新视图,插入了您的地图功能,但我不清楚我在哪里设置列表(或显示)代码。它是在蒲团的“地图”区域还是其他地方?我还尝试将其作为列表插入到地图功能下方,但无法正确设置,蒲团也不会接受。非常感谢您的意见。【参考方案2】:

这里是设计文档中所有功能的完整参考。我希望我不会错过任何括号;)


   "_id": "_design/[ddoc name]",

   "views": 
      "[view name]": 
         "map": "[map function]"
      
   ,
   "language": "javascript",
   "lists": 
      "[list name]": "[list function]"
   ,
   "shows": 
      "[show name]": "[show function]"
   ,
   "updates": 
       "[update name]": "[update function]"
   ,
   "filters": 
      "[filter name]": "[filter function]"
   

缩小 JavaScript 代码也很重要。

【讨论】:

嗨@Sceada。请参阅我上面的编辑。谢谢您的照顾。这显然是 CouchDB 的重要组成部分。 嗨@Sceada。请参阅我上面的edit2。它花了我很长时间。如果你的耐心还在。【参考方案3】:

很抱歉我的回复晚了。我正在度假。你的语法不正确。

function(head, req) 
  var result = [];
  while (row = getRow()) 
      if (row !== null) 
          // This is not correct, you have to assigne the result to a  
          // variable. 
          // You also have to assigne something to the array result.
          // result.append();
          // So if row.key and row.value are both numbers and you want
          // the result you have to write
          // temp = row.key + row.value;
          // result.append(temp);
          //row.key + row.value
        else 
            send(JSON.stringify(
                status_code: 404
            ));
        
    
    send(JSON.stringify(result));
  

【讨论】:

以上是关于CouchDB 视图(map/reduce)的主要内容,如果未能解决你的问题,请参考以下文章

couchdb - Map Reduce - 如何在 Reduce 函数中加入不同的文档和组结果

CouchDB reduce 函数给出了意想不到的结果

MongoDB与CouchDB 全方位对比

如何有效地将 CouchDB 与规范化数据一起使用?

MongoDB下Map-Reduce使用简单翻译及示例

python 之 map/reduce