我开始使用neo4j。
在我的图形数据库中,我有节点Person
(请看下面的“ John”),其标签为:Name
(字符串),Food
(正整数)。每个Person
通过具有值的关系Person
与其他isFriendTo
连接。
我仅使用图数据库来查找两个人之间的最短加权路径。
此外,每天我都要检查图中的每个节点,如果食物的价值低于100,我会采取一些措施。
现在,在进行一些改进之后,属性Food
不足以容纳我的项目。因此,我必须将其拆分为其他三个更具体的属性(正整数):Vegetables
,Meat
和Cereals
。如果这三个值之和小于100,则我必须采取与以前相同的操作。
我以前的情况是“约翰”,我可以将设计发展到的唯一选择是“弗雷德”还是“保罗”?
我可以通过哪种方式设计它?除了neo4j之外,我是否还应该使用MongoDB之类的东西来表示层次结构?
删除属性Food并添加三个新属性对我来说似乎是一个坏习惯。我必须在其他地方保存该3表示“食物” ...如果将来我会添加其他类型的食物呢?在哪里存储要检查的值100必须来自Meat
,Vegetables
和Cereals
的知识?
拥有这样的东西可以解决我的疑问,因为我可以对food
中的所有项求和:
{
"name": "Lucas",
"food": {
"meat": 40,
"vegetables": 30,
"cereals": 0
}
}
(我不需要遍历从Food
和Vegetables
到Person
的连接。只需要检查肉类,蔬菜和谷物的总和是较小还是较大100。)
答案 0 :(得分:1)
根据您的图表,Person
似乎是所有节点共享的 label ,而Name/Food//Meat/Vegetables/Cererals
似乎是节点 properties的名称。
如果我的理解是正确的,那么有很多方法可以处理多种食物类型,并获得每人总计。以下是几个示例。
这是一种方法。您可以为unique食物类型节点引入Food
标签:
(:Food {type: 'Meat'}), (:Food {type: 'Vegetable'}), etc.
,每个Person
节点可以与每个相关的Food节点具有HAS_FOOD
关系(具有amount
属性)(而不是在内部存储食物类型属性):
(john:Person {Name: 'John'})-[:HAS_FOOD {amount: 140}]->(meat:Food {type: 'Meat'})
使用此数据模型,可以找到包含100单位以上食物的所有Person
:
MATCH (p:Person)-[r:HAS_FOOD]->()
WITH p, SUM(r.amount) AS total
WHERE total > 100
RETURN p;
这是另一种方法(可能会加快搜索速度)。由于neo4j属性不能具有映射值(与您在问题底部附近的JSON中显示的值相反),因此每个Person
节点都可以具有amount
和food
数组,如下所示:
(:Person {Name: 'Fred', amount: [50, 100], food: ['Meat','Vegetables']})
使用此数据模型,可以找到包含100单位以上食物的所有Person
:
MATCH (p:Person)
WHERE REDUCE(s = 0, a IN p.amount | s + a) > 100
RETURN p;
[更新]
但是,使用第二种方法进行食品加工(很好,这里是双关语)可能比较麻烦且效率较低。例如,这是获取Fred
的肉量的一种方法:
MATCH (p:Person {Name: 'Fred'})
RETURN [i IN RANGE(0, SIZE(p.food)-1) WHERE p.food[i] = 'Meat' | p.amount[i]][0] AS meatAmt;
然后将Fred
的肉类数量设置为123:
MATCH (p:Person {Name: 'Fred'})
SET p.amount = [i IN RANGE(0, SIZE(p.food)-1) | CASE WHEN p.food[i] = 'Meat' THEN 123 ELSE p.amount[i]];
因此,这是解决您的问题的第三种方法,并且对于执行食品加工而言要好得多。每个“人”节点都可以将食物量直接存储为属性,例如:
(:Person {Name: 'Fred', Meat: 50, Vegetables: 100, foodNames: ['Meat', 'Vegetables']})
使用此数据模型,foodNames
数组可让您按名称遍历食物属性。因此,要查找所有食物量超过100个单位的人:
MATCH (p:Person)
WHERE REDUCE(s = 0, n IN p.foodNames | s + p[n]) > 100
RETURN p;
然后,获取Fred
的肉量:
MATCH (p:Person {Name: 'Fred'})
RETURN p.Meat AS meatAmt;
要将Fred
的肉量设置为123:
MATCH (p:Person {Name: 'Fred'})
SET p.Meat = 123;
答案 1 :(得分:0)
在Neo4j上,标签就像标签一样,没有技术层次,并且一个节点可以有很多标签。
但是从业务的角度来看,如果您想说Food
是Vegetables
,Meat
和Cereals
的父级,那就没有问题了。您将具有业务/语义层次。
因此,从我的观点来看,在您的情况下,我只会在标签为Food
的节点上添加新标签