Couchbase Server 4.6.1下用N1QL查看文档树及获取修订体咨询
Couchbase里的文档都是JSON格式,要是你的数据本身是树状结构(比如有父子节点关联,或者文档内部嵌套了层级化的数组),用N1QL的递归CTE(公共表表达式)就能轻松遍历出树状结构,4.6.1版本已经支持这个特性了。
分两种情况给你举例:
情况一:跨文档的树状结构(比如用parent_id关联父子文档)
假设你的bucket里的文档都有id、name和parent_id字段(根节点的parent_id为NULL),可以用下面的递归查询来生成完整的树:WITH RECURSIVE tree AS ( -- 先找出所有根节点 SELECT id, name, parent_id, ARRAY[] AS path FROM `your-bucket-name` WHERE parent_id IS NULL UNION ALL -- 递归遍历子节点,把父节点的路径传递下去 SELECT c.id, c.name, c.parent_id, ARRAY_APPEND(p.path, p.name) AS path FROM tree p JOIN `your-bucket-name` c ON p.id = c.parent_id ) SELECT * FROM tree ORDER BY path;这个查询会返回每个节点的完整层级路径,方便你查看树状结构。
情况二:单文档内部的嵌套树结构
如果树状结构是嵌套在单个文档里的(比如一个文档里有root字段,下面包含children数组递归嵌套),可以结合UNNEST和递归CTE来拆解:WITH RECURSIVE doc_tree AS ( -- 先取出根节点 SELECT obj.id, obj.name, obj.children, ARRAY[obj.name] AS hierarchy FROM `your-bucket-name` b UNNEST b.root AS obj WHERE b.id = "target-doc-id" -- 替换成你要查看的文档ID UNION ALL -- 递归遍历每个节点的子节点 SELECT child.id, child.name, child.children, ARRAY_APPEND(dt.hierarchy, child.name) AS hierarchy FROM doc_tree dt UNNEST dt.children AS child ) SELECT id, name, hierarchy FROM doc_tree;这个查询会把嵌套的树结构展开,每个节点的层级关系通过
hierarchy数组清晰展示。
针对这个问题,我得先澄清一个关键点:Couchbase Server本身不会自动在文档里保存所有修订历史列表——你看到的每个文档里的修订历史,应该是你的应用程序在更新文档时主动添加进去的(比如维护了一个revisions数组)。
如果是应用自己存储的修订历史,那完全可以用N1QL获取指定版本的内容:
假设你的文档结构是这样的:
{ "id": 123, "_deleted": true, "_rev": "4-54gtrg", "revisions": [ {"_rev": "1-abc", "content": {"key1": "old-value1"}}, {"_rev": "2-def", "content": {"key1": "updated-value"}}, {"_rev": "3-dsada", "content": {"key1": "version3-value"}}, {"_rev": "4-54gtrg", "content": {"_deleted": true}} ] }
你可以用下面的N1QL语句精准提取3-dsada版本的内容:
SELECT rev.content FROM `your-bucket-name` d UNNEST d.revisions AS rev WHERE d.id = 123 AND rev._rev = "3-dsada";
但如果这个修订历史不是应用存储的,而是你误以为Couchbase系统自动保留的——那很遗憾,Couchbase的MVCC机制只会在短时间内保留旧版本(比如为了处理并发事务、视图索引的增量更新),不会持久化存储所有历史版本,所以无法通过N1QL查询到系统层面的旧版本内容。如果需要长期保留历史版本,你得在应用层实现版本控制逻辑:比如每次更新时把旧版本内容存入文档的数组中,或者单独存储到另一个bucket里。
内容的提问来源于stack exchange,提问作者Kolzar

