从 CouchDB 检索分层/嵌套数据
我对 couchDB 很陌生,甚至在阅读 (最新存档现已删除)http://wiki.apache.org/couchdb/How_to_store_hierarchical_data(通过“存储每个节点的完整路径作为该节点文档中的属性') 它仍然没有单击。
我希望将子项作为 UUID 数组来跟踪,将父项作为单个 UUID 来跟踪,而不是使用 wiki 中描述的完整路径模式。我倾向于这种模式,这样我就可以通过子项在子项数组中的位置来维护子项的顺序。
以下是沙发中的一些示例文档,桶可以包含桶和项目,项目只能包含其他项目。 (为了清楚起见,缩写了 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}
]}
]}
]
}
I'm pretty new to couchDB and even after reading (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’) it's still not clicking just yet.
Instead of using the full path pattern as described in the wiki I'm hoping to keep track of children as an array of UUIDs and the parent as a single UUID. I'm leaning towards this pattern so I can maintain the order of children by their positions in the children array.
Here are some sample documents in couch, buckets can contain buckets and items, items can only contain other items. (UUIDs abbreviated for clarity):
{_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
}
Is it possible to look up a document by an embedded document id within a map function?
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
}
}
}
}
In an ideal world final JSON output would look something like.
{"_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}
]}
]}
]
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您可以在 CouchDB wiki 上找到一般性讨论。
我现在没有时间测试它,但是您的地图函数应该类似于:
您应该使用
include_docs=true
查询它以获取文档,如 CouchDB 文档:如果您的地图函数发出一个具有{'_id 的对象值': XXX}
并且使用include_docs=true
参数查询视图,那么 CouchDB 将获取 id XXX 的文档,而不是经过处理以发出键/值对的文档。添加
startkey=["3944"]&endkey["3944",{}]
以仅获取 ID 为“3944”的文档及其子文档。编辑:查看此问题了解更多详细信息。
You can find a general discussion on the CouchDB wiki.
I have no time to test it right now, however your map function should look something like:
You should query it with
include_docs=true
to get the documents, as explained in the CouchDB documentation: if your map function emits an object value which has{'_id': XXX}
and you query view withinclude_docs=true
parameter, then CouchDB will fetch the document with id XXX rather than the document which was processed to emit the key/value pair.Add
startkey=["3944"]&endkey["3944",{}]
to get only the document with id "3944" with its children.EDIT: have a look at this question for more details.
可以从视图中输出树结构吗?不能。CouchDB 视图查询返回一个值列表,没有办法让它们输出除列表之外的任何内容。因此,您必须处理返回给定存储桶的所有后代列表的映射。
但是,您可以在查看本身,将该列表转回嵌套结构。如果您的值知道其父级的
_id
,这是可能的 - 该算法相当简单,如果它给您带来麻烦,只需问另一个问题即可。您可以在地图函数中通过 ID 获取文档吗? 不可以。无法从 CouchDB 中通过标识符获取文档。请求必须来自应用程序,采用文档标识符上的标准
GET
形式,或者通过将include_docs=true
添加到视图请求中。其技术原因非常简单:CouchDB 仅在文档更改时运行映射函数。如果允许文档
A
获取文档B
,那么当B
发生更改时,发出的数据将变得无效。是否可以在不存储每个节点的父节点列表的情况下输出所有后代? 不能。CouchDB 映射函数为数据库中的每个文档发出一组键-值-id 对,因此键之间的对应关系并且id必须根据单个文档来确定。
如果你有一个四级树结构
A -> B-> C-> D
但只让一个节点知道它的父节点和子节点,那么上面的节点都不知道D
是A
的后代,所以你不会能够使用基于A
的键发出D
的 id,因此它在输出中不可见。因此,您有三个选择:
B
知道C
是A
的后代),然后抓取通过再次运行查询来增加级别。Can you output a tree structure from a view? No. CouchDB view queries return a list of values, there is no way to have them output anything other than a list. So, you have to deal with your map returning the list of all descendants of a given bucket.
You can, however, plug a
_list
post-processing function after the view itself, to turn that list back into a nested structure. This is possible if your values know the_id
of their parent — the algorithm is fairly straightforward, just ask another question if it gives you trouble.Can you grab a document by its id in the map function? No. There's no way to grab a document by its identifier from within CouchDB. The request must come from the application, either in the form of a standard
GET
on the document identifier, or by addinginclude_docs=true
to a view request.The technical reason for this is pretty simple: CouchDB only runs the map function when the document changes. If document
A
was allowed to fetch documentB
, then the emitted data would become invalid whenB
changes.Can you output all descendants without storing the list of parents of every node? No. CouchDB map functions emit a set of key-value-id pairs for every document in the database, so the correspondence between the key and the id must be determined based on a single document.
If you have a four-level tree structure
A -> B -> C -> D
but only let a node know about its parent and children, then none of the nodes above know thatD
is a descendant ofA
, so you will not be able to emit the id ofD
with a key based onA
and thus it will not be visible in the output.So, you have three choices:
B
knows thatC
is a descendant ofA
), and grab additional levels by running the query again.