Arangodb:在树状结构中引用叶子的最佳建模策略
Arangodb: Best modelling strategy to reference leaf in a tree like structure
给定一个修复 3 层的深树结构,例如
collection: 树
{
"name": "Level 1",
"children": [{
"name": "Level 1.1",
"children": [{
"name": "Level 1.1.1"
}, {
"name": "Level 1.1.2"
}]
}, {
"name": "Level 1.2",
"children": [{
"name": "Level 1.2.1"
}]
}]
}
并且在另一个 collection 中引用了一个 "leaf" 节点:
collection "person"
{
"name": {
"first": "John",
"last": "Doe"
},
"linkToLeaf": "<need to reference a leaf node. e.g. 'Level 1.2.1'>"
}
并且需要查询数据到:
- 呈现树以便管理员用户可以组织层次结构(基本 CRUD 页面)
- 在某个地方显示面包屑"You are in: Level 1 > Level 1.2 > Level 1.2.1"
- 建立link到"leaf node"
使用 arangodb,建模数据的最佳方式是什么?使用图表,简单的 JSON 文件,两者的混合,还有别的吗?
我正在做一个新项目,我们想跳转到 NoSQL,但是来自传统 RDBMS 的背景,我会简单地使用递归连接对树建模,因此简单地引用 "leaf node"使用它的主键。
不知道怎么做 Arangodb...
有几点会对您的数据模型产生影响:
- 与常规数据库一样,连接不是免费的。将来自多个集合的数据聚合到一个文档中可能会有所帮助。
- 根据您要更新的内容,使用深度结构化的文档可能会变得很有挑战性,并且会产生难以阅读的 AQL。
在你的例子中,你展示了一些看起来非常相似的东西,像分形一样嵌套。
你可以肯定地把它弄平,然后通过图形遍历嵌套做你所做的事情。
这对于您在客户端的代码可能是有益的,您不仅会被绑定到固定数量的层;
Graph traversals 产生非常好的行为,您甚至可以迭代更深的动态。
新的 ArangoDB 模式匹配遍历看起来像这样:
db._create("names");
db.names.save({_key: "Level1"});
db.names.save({_key: "Level1.1"});
db.names.save({_key: "Level1.1.1"});
db.names.save({_key: "Level1.1.2"});
db.names.save({_key: "Level1.1.3"});
db.names.save({_key: "Level1.2"});
db.names.save({_key: "Level1.2.1"});
db._createEdgeCollection("nameEdges")
db.nameEdges.save("names/Level1", "names/Level1.1", {layer: 0})
db.nameEdges.save("names/Level1.1", "names/Level1.1.1", {layer: 1})
db.nameEdges.save("names/Level1.1", "names/Level1.1.2", {layer: 1})
db.nameEdges.save("names/Level1.1", "names/Level1.1.3", {layer: 1})
db.nameEdges.save("names/Level1", "names/Level1.2", {layer: 0})
db.nameEdges.save("names/Level1.2", "names/Level1.2.1", {layer: 1})
db._create("persons")
db.persons.save({_key: "adam_ant", details: {cname: "adam", lname: "ant"}})
db.persons.save({_key: "david_bowie", details:
{cname: "david", lname: "bowie"}})
db._createEdgeCollection("nameToPersons")
db.nameToPersons.save("names/Level1", "persons/adam_ant",
{himself: true})
db.nameToPersons.save("names/Level1.2", "persons/david_bowie",
{alien: true})
递归结构:
db._query("FOR v IN 1..3 OUTBOUND 'names/Level1' nameEdges RETURN v"
).toArray()
连接人;我们向他们显示顶点、边和路径:
db._query("FOR v, e, p IN 1..4 OUTBOUND 'names/Level1' " +
"nameEdges,nameToPersons " +
"RETURN {v:v, e:e, p:p}").toArray()
您可以对 edges、vertices 和 paths 的任意属性进行过滤:
db._query("FOR v, e, p IN 1..4 OUTBOUND 'names/Level1' " +
"nameEdges,nameToPersons " +
"FILTER e.alien != true " +
"RETURN {v:v}").toArray()
给定一个修复 3 层的深树结构,例如
collection: 树
{
"name": "Level 1",
"children": [{
"name": "Level 1.1",
"children": [{
"name": "Level 1.1.1"
}, {
"name": "Level 1.1.2"
}]
}, {
"name": "Level 1.2",
"children": [{
"name": "Level 1.2.1"
}]
}]
}
并且在另一个 collection 中引用了一个 "leaf" 节点:
collection "person"
{
"name": {
"first": "John",
"last": "Doe"
},
"linkToLeaf": "<need to reference a leaf node. e.g. 'Level 1.2.1'>"
}
并且需要查询数据到:
- 呈现树以便管理员用户可以组织层次结构(基本 CRUD 页面)
- 在某个地方显示面包屑"You are in: Level 1 > Level 1.2 > Level 1.2.1"
- 建立link到"leaf node"
使用 arangodb,建模数据的最佳方式是什么?使用图表,简单的 JSON 文件,两者的混合,还有别的吗?
我正在做一个新项目,我们想跳转到 NoSQL,但是来自传统 RDBMS 的背景,我会简单地使用递归连接对树建模,因此简单地引用 "leaf node"使用它的主键。
不知道怎么做 Arangodb...
有几点会对您的数据模型产生影响:
- 与常规数据库一样,连接不是免费的。将来自多个集合的数据聚合到一个文档中可能会有所帮助。
- 根据您要更新的内容,使用深度结构化的文档可能会变得很有挑战性,并且会产生难以阅读的 AQL。
在你的例子中,你展示了一些看起来非常相似的东西,像分形一样嵌套。 你可以肯定地把它弄平,然后通过图形遍历嵌套做你所做的事情。 这对于您在客户端的代码可能是有益的,您不仅会被绑定到固定数量的层; Graph traversals 产生非常好的行为,您甚至可以迭代更深的动态。
新的 ArangoDB 模式匹配遍历看起来像这样:
db._create("names");
db.names.save({_key: "Level1"});
db.names.save({_key: "Level1.1"});
db.names.save({_key: "Level1.1.1"});
db.names.save({_key: "Level1.1.2"});
db.names.save({_key: "Level1.1.3"});
db.names.save({_key: "Level1.2"});
db.names.save({_key: "Level1.2.1"});
db._createEdgeCollection("nameEdges")
db.nameEdges.save("names/Level1", "names/Level1.1", {layer: 0})
db.nameEdges.save("names/Level1.1", "names/Level1.1.1", {layer: 1})
db.nameEdges.save("names/Level1.1", "names/Level1.1.2", {layer: 1})
db.nameEdges.save("names/Level1.1", "names/Level1.1.3", {layer: 1})
db.nameEdges.save("names/Level1", "names/Level1.2", {layer: 0})
db.nameEdges.save("names/Level1.2", "names/Level1.2.1", {layer: 1})
db._create("persons")
db.persons.save({_key: "adam_ant", details: {cname: "adam", lname: "ant"}})
db.persons.save({_key: "david_bowie", details:
{cname: "david", lname: "bowie"}})
db._createEdgeCollection("nameToPersons")
db.nameToPersons.save("names/Level1", "persons/adam_ant",
{himself: true})
db.nameToPersons.save("names/Level1.2", "persons/david_bowie",
{alien: true})
递归结构:
db._query("FOR v IN 1..3 OUTBOUND 'names/Level1' nameEdges RETURN v"
).toArray()
连接人;我们向他们显示顶点、边和路径:
db._query("FOR v, e, p IN 1..4 OUTBOUND 'names/Level1' " +
"nameEdges,nameToPersons " +
"RETURN {v:v, e:e, p:p}").toArray()
您可以对 edges、vertices 和 paths 的任意属性进行过滤:
db._query("FOR v, e, p IN 1..4 OUTBOUND 'names/Level1' " +
"nameEdges,nameToPersons " +
"FILTER e.alien != true " +
"RETURN {v:v}").toArray()