我对couchDB很新,甚至在阅读(latest archive as now deleted) http://wiki.apache.org/couchdb/How_to_store_hierarchical_data (via ‘Store the full path to each node as an attribute in that node's document’)之后,它仍然没有点击。
我没有使用wiki中描述的完整路径模式,而是希望将子节点跟踪为UUID数组,将父节点视为单个UUID。我倾向于这种模式,所以我可以通过他们在儿童阵列中的位置维持儿童的顺序。
以下是沙发中的一些示例文档,存储桶可以包含存储桶和项目,项目只能包含其他项目。 (UUID缩写为清晰):
{_id: 3944
name: "top level bucket with two items"
type: "bucket",
parent: null
children: [8989, 4839]
}
{_id: 8989
name: "second level item with no sub items"
type: "item"
parent: 3944
}
{
_id: 4839
name: "second level bucket with one item"
type: "bucket",
parent: 3944
children: [5694]
}
{
_id: 5694
name: "third level item (has one sub item)"
type: "item",
parent: 4839,
children: [5390]
}
{
_id: 5390
name: "fourth level item"
type: "item"
parent: 5694
}
是否可以通过地图功能中的嵌入式文档ID查找文档?
function(doc) {
if(doc.type == "bucket" || doc.type == "item")
emit(doc, null); // still working on my key value output structure
if(doc.children) {
for(var i in doc.children) {
// can i look up a document here using ids from the children array?
doc.children[i]; // psuedo code
emit(); // the retrieved document would be emitted here
}
}
}
}
在理想世界中,最终的JSON输出看起来像。
{"_id":3944,
"name":"top level bucket with two items",
"type":"bucket",
"parent":"",
"children":[
{"_id":8989, "name":"second level item with no sub items", "type":"item", "parent":3944},
{"_id": 4839, "name":"second level bucket with one item", "type":"bucket", "parent":3944, "children":[
{"_id":5694", "name":"third level item (has one sub item)", "type":"item", "parent": 4839, "children":[
{"_id":5390, "name":"fourth level item", "type":"item", "parent":5694}
]}
]}
]
}
答案 0 :(得分:7)
您可以从视图输出树结构吗? No. CouchDB视图查询返回值列表,没有办法让它们输出除列表之外的任何内容。因此,您必须处理您的地图,返回给定存储桶的所有后代的列表。
但是,您可以在视图本身之后插入_list
后处理函数,以将该列表重新转换为嵌套结构。如果您的值知道其父级的_id
,则可以实现这一点 - 算法非常简单,如果它给您带来麻烦,只需提出另一个问题。
您可以在地图功能中按ID获取文档吗?否。无法通过CouchDB中的标识符获取文档。请求必须来自应用程序,可以是文档标识符上的标准GET
形式,也可以是include_docs=true
添加到查看请求中。
技术原因非常简单:CouchDB仅在文档更改时运行map函数。如果允许文档A
获取文档B
,那么当B
更改时,发出的数据将无效。
你可以输出所有后代而不存储每个节点的父节点列表吗? No. CouchDB映射函数为数据库中的每个文档发出一组键值id对,所以对应密钥和id之间必须根据单个文档确定。
如果你有一个四级树结构A -> B -> C -> D
,但只让节点知道它的父节点和子节点,那么上述节点都不知道D
是A
的后代},因此您将无法使用基于D
的密钥发出A
的ID,因此它在输出中不可见。
所以,你有三个选择:
B
知道C
是A
的后代),并通过再次运行查询来获取其他级别。答案 1 :(得分:6)
您可以找到一般性讨论on the CouchDB wiki。
我现在没时间测试它,但是你的地图功能应该类似于:
function(doc) {
if (doc.type === "bucket" || doc.type === "item")
emit([ doc._id, -1 ], 1);
if (doc.children) {
for (var i = 0, child_id; child_id = doc.children[i]; ++i) {
emit([ doc._id, i ], { _id: child_id });
}
}
}
}
您应该使用include_docs=true
进行查询以获取文档,如CouchDB documentation中所述:如果您的地图函数发出的对象值为{'_id': XXX}
,并且您使用{{查询视图1}}参数,然后CouchDB将获取ID为XXX的文档,而不是处理为发出键/值对的文档。
添加include_docs=true
以仅获取ID为“3944”及其子项的文档。
编辑:有关详细信息,请查看this question。