Database design 图数据库中的层次属性
我开始使用neo4j。 在我的图形数据库中,我让下面的节点人员查看John,标签为:名称字符串,食物正整数。每个人都通过关系isFriendTo与其他人建立联系,这是有价值的。 我使用图DB只是为了找到两个人之间最短的加权路径 此外,每天我都会检查图中的每个节点,如果食物的值低于100,我会采取一些措施 现在,经过一些改进后,我的项目不再需要食物了。所以我必须把它分成另外三个更具体的正整数:蔬菜,肉类和谷物。如果三者之和都小于100,我必须采取与以前相同的行动。 我以前的情况是,作为约翰,我能改变我设计的唯一选择是弗雷德还是保罗 我可以用哪种方式设计这个?除了neo4j之外,我还应该使用MongoDB之类的东西来表示层次结构吗 移除属性食物并添加三个新属性对我来说似乎是一个坏习惯。我必须在其他地方保存这3个意味着食物。。。如果将来我会添加其他类型的食物呢?要检查的值100必须来自肉类、蔬菜和谷物的总和,我在哪里存储这些知识? 有这样的东西可以解决我的疑问,因为我可以计算食物中的所有项目:Database design 图数据库中的层次属性,database-design,neo4j,nosql,cypher,graph-databases,Database Design,Neo4j,Nosql,Cypher,Graph Databases,我开始使用neo4j。 在我的图形数据库中,我让下面的节点人员查看John,标签为:名称字符串,食物正整数。每个人都通过关系isFriendTo与其他人建立联系,这是有价值的。 我使用图DB只是为了找到两个人之间最短的加权路径 此外,每天我都会检查图中的每个节点,如果食物的值低于100,我会采取一些措施 现在,经过一些改进后,我的项目不再需要食物了。所以我必须把它分成另外三个更具体的正整数:蔬菜,肉类和谷物。如果三者之和都小于100,我必须采取与以前相同的行动。 我以前的情况是,作为约翰,我能改
我不需要遍历从食物和蔬菜到人的连接。只需要检查一下肉类、蔬菜的总量。谷物小于或大于100。在Neo4j上,标签类似于标签,没有技术层次结构,一个节点可以有许多标签 但是,如果你想说,从你的商业角度来看,食品是蔬菜、肉类和谷类食品的母体,那就没有问题了。您将拥有一个业务/语义层次结构
因此,从我的观点来看,在你的情况下,我只会在你的节点上添加新标签,标签为Food,看起来你混淆了术语和 根据您的图表,Person似乎是所有节点共享的标签,Name/Food//Meat/vegets/Cererals似乎是节点属性的名称 如果我的理解是正确的,那么有很多方法来处理多种食物类型的数量,并得到每个人的总数。下面是几个例子 这里有一种方法。您可以为食物类型节点引入食物标签:
(:Food {type: 'Meat'}), (:Food {type: 'Vegetable'}), etc.
并且每个人节点可以具有与每个相关食物节点的数量属性的HAS_食物关系,而不是在内部存储食物类型属性:
(john:Person {Name: 'John'})-[:HAS_FOOD {amount: 140}]->(meat:Food {type: 'Meat'})
使用此数据模型,要查找食物量超过100单位的所有人:
MATCH (p:Person)-[r:HAS_FOOD]->()
WITH p, SUM(r.amount) AS total
WHERE total > 100
RETURN p;
MATCH (p:Person)
WHERE REDUCE(s = 0, a IN p.amount | s + a) > 100
RETURN p;
MATCH (p:Person)
WHERE REDUCE(s = 0, n IN p.foodNames | s + p[n]) > 100
RETURN p;
这是另一种可能导致更快搜索的方法。由于neo4j属性的map值不能与问题底部JSON中显示的值相反,因此每个Person节点都可以有amount和food数组,如下所示:
(:Person {Name: 'Fred', amount: [50, 100], food: ['Meat','Vegetables']})
(:Person {Name: 'Fred', Meat: 50, Vegetables: 100, foodNames: ['Meat', 'Vegetables']})
使用此数据模型,要查找食物量超过100单位的所有人:
MATCH (p:Person)-[r:HAS_FOOD]->()
WITH p, SUM(r.amount) AS total
WHERE total > 100
RETURN p;
MATCH (p:Person)
WHERE REDUCE(s = 0, a IN p.amount | s + a) > 100
RETURN p;
MATCH (p:Person)
WHERE REDUCE(s = 0, n IN p.foodNames | s + p[n]) > 100
RETURN p;
[更新]
然而,在这里,用第二种方法处理食品可能会更麻烦、效率更低。例如,这是为Fred获取肉类数量的一种方法:
并且,要将Fred的肉量设置为123:
所以,这里有第三种方法可以解决您的问题,并且对执行食品加工更好。每个Person节点可以将食物量直接存储为属性,如下所示:
(:Person {Name: 'Fred', amount: [50, 100], food: ['Meat','Vegetables']})
(:Person {Name: 'Fred', Meat: 50, Vegetables: 100, foodNames: ['Meat', 'Vegetables']})
使用此数据模型,foodNames数组允许您按名称遍历食物属性。因此,要找到所有食物量超过100单位的人:
MATCH (p:Person)-[r:HAS_FOOD]->()
WITH p, SUM(r.amount) AS total
WHERE total > 100
RETURN p;
MATCH (p:Person)
WHERE REDUCE(s = 0, a IN p.amount | s + a) > 100
RETURN p;
MATCH (p:Person)
WHERE REDUCE(s = 0, n IN p.foodNames | s + p[n]) > 100
RETURN p;
为了给弗雷德弄到肉的份量:
要将Fred的肉量设置为123:
食物不是节点。在我的第一个版本中,代码是一个标签。很抱歉,这是对语言的滥用:使用标签FoodOk在节点上添加新标签,因此你的意思是,不是我最初的想法,即从节点Person中删除标签Food。对你来说,最好是保留它并有标签:食物、蔬菜、肉类和谷物?我的意思是,如果你有节点胡萝卜,这个节点应该有标签食物和蔬菜。我编辑了我的原始帖子,也许现在它更清晰了。谢谢!第二种方法是我想要的,简单快捷。我已经想到了第一种解决方案,但我想增加不必要的复杂性,因为我不需要遍历这些节点。我如何才能为Fred获得足够的肉?我有一种更好的第三种方法。查看我的更新答案。我更喜欢这个新解决方案:在每个人身上重复食物名称是可以的,或者我可以把它外部化吗?你说的外部化是什么意思?