我正在寻找与“SQL连接”等效的CouchDB。
在我的示例中,有些列表元素的CouchDB文档:
{ "type" : "el", "id" : "1", "content" : "first" }
{ "type" : "el", "id" : "2", "content" : "second" }
{ "type" : "el", "id" : "3", "content" : "third" }
有一个文档定义了列表:
{ "type" : "list", "elements" : ["2","1"] , "id" : "abc123" }
正如您所看到的,第三个元素已被删除,它不再是列表的一部分。所以它不能成为结果的一部分。现在我想要一个返回内容元素的视图,包括正确的顺序。
结果可能是:
{ "content" : ["second", "first"] }
在这种情况下,元素的顺序已经是应该的。另一个可能的结果是:
{ "content" : [{"content" : "first", "order" : 2},{"content" : "second", "order" : 1}] }
我开始编写地图功能:
map = function (doc) {
if (doc.type === 'el') {
emit(doc.id, {"content" : doc.content}); //emit the id and the content
exit;
}
if (doc.type === 'list') {
for ( var i=0, l=doc.elements.length; i<l; ++i ){
emit(doc.elements[i], { "order" : i }); //emit the id and the order
}
}
}
这是我能得到的。你能纠正我的错误并写一个reduce函数吗?请记住,第三个文档不得是结果的一部分。
当然你也可以写一个不同的地图功能。但是文档的结构(一个definig元素文档和每个条目的条目文档)不能改变。
编辑:不要错过JasonSmith对他的回答的评论,他在那里描述了如何做到这一点。
答案 0 :(得分:51)
谢谢!这是炫耀CouchDB 0.11's new features的一个很好的例子!
您必须使用与提取相关的数据功能来引用文档
在视图中。可选地,为了更方便的JSON,使用_list
函数
清理结果。有关详细信息,请参阅Couchio's writeup on "JOIN"s。
这是计划:
首先,您的el
文档中有唯一性约束。如果两个
他们有id = 2,这是一个问题。有必要使用
如果_id
,请改为id
字段。 CouchDB将保证唯一性,但是,
此计划的其余部分需要_id
才能按ID获取文档。
{ "type" : "el", "_id" : "1", "content" : "first" }
{ "type" : "el", "_id" : "2", "content" : "second" }
{ "type" : "el", "_id" : "3", "content" : "third" }
如果更改文档以使用_id
是绝对不可能的,您可以
创建一个简单的视图emit(doc.id, doc)
,然后重新插入到。{1}}
临时数据库。这会将id
转换为_id
,但会增加一些复杂性。
视图会发出键入的{"_id": content_id}
数据
[list_id, sort_number]
,用他们的内容“聚集”列表。
function(doc) {
if(doc.type == 'list') {
for (var i in doc.elements) {
// Link to the el document's id.
var id = doc.elements[i];
emit([doc.id, i], {'_id': id});
}
}
}
现在有一个简单的el
文档列表,顺序正确。您可以
如果您只想查看特定列表,请使用startkey
和endkey
。
curl localhost:5984/x/_design/myapp/_view/els
{"total_rows":2,"offset":0,"rows":[
{"id":"036f3614aeee05344cdfb66fa1002db6","key":["abc123","0"],"value":{"_id":"2"}},
{"id":"036f3614aeee05344cdfb66fa1002db6","key":["abc123","1"],"value":{"_id":"1"}}
]}
要获取el
内容,请使用include_docs=true
进行查询。通过魔术
_id
,el
文档将加载。
curl localhost:5984/x/_design/myapp/_view/els?include_docs=true
{"total_rows":2,"offset":0,"rows":[
{"id":"036f3614aeee05344cdfb66fa1002db6","key":["abc123","0"],"value":{"_id":"2"},"doc":{"_id":"2","_rev":"1-4530dc6946d78f1e97f56568de5a85d9","type":"el","content":"second"}},
{"id":"036f3614aeee05344cdfb66fa1002db6","key":["abc123","1"],"value":{"_id":"1"},"doc":{"_id":"1","_rev":"1-852badd683f22ad4705ed9fcdea5b814","type":"el","content":"first"}}
]}
请注意,这已经是您需要的所有信息。如果您的客户是 灵活,你可以解析这个JSON的信息。下一个可选 步骤只需重新格式化,以符合您的需要。
使用_list
函数,它只是重新格式化视图输出。人们使用它们输出XML或HTML,但我们会做
JSON更方便。
function(head, req) {
var headers = {'Content-Type': 'application/json'};
var result;
if(req.query.include_docs != 'true') {
start({'code': 400, headers: headers});
result = {'error': 'I require include_docs=true'};
} else {
start({'headers': headers});
result = {'content': []};
while(row = getRow()) {
result.content.push(row.doc.content);
}
}
send(JSON.stringify(result));
}
结果匹配。当然,在制作中,您需要startkey
和endkey
来指定所需的列表。
curl -g 'localhost:5984/x/_design/myapp/_list/pretty/els?include_docs=true&startkey=["abc123",""]&endkey=["abc123",{}]'
{"content":["second","first"]}