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)的主要内容,如果未能解决你的问题,请参考以下文章