图数据库中的层次结构属性 [英] hierarchy property in graph database
问题描述
我开始使用neo4j.
在我的图形数据库中,我有节点Person
(请看下面的"John"),其标签为:Name
(字符串),Food
(正整数).每个Person
通过具有值的关系isFriendTo
与其他Person
连接.
我仅使用图数据库来查找两个人之间的最短加权路径.
此外,每天我都要检查图中的每个节点,如果食物的价值低于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.)
似乎您对术语属性.
根据您的图表,Person
似乎是所有节点共享的 label ,而Name/Food//Meat/Vegetables/Cererals
似乎是节点 properties 的名称. /p>
如果我的理解是正确的,那么有很多方法可以处理多种食物类型,并获得每人总计.以下是几个示例.
-
因此,这是解决您的问题的第三种方法,并且对于执行食品加工而言要好得多.每个人"节点都可以将食物数量直接存储为属性,例如:
(: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;
I'm starting to use neo4j.
In my graph database I've the nodes Person
(look at "John" below), with the labels: Name
(string), Food
(positive integer). Each Person
is connected with other Person
through the relationship isFriendTo
, that has a value.
I use the graph DB only to find the shortest weighted path between two person.
Also, every day I check every node in the graph, and if the food go under value of 100, I take some actions.
Now, after some improvements, the property Food
is no more enough for my project. So I have to split this in three other more specific property (positive integer): Vegetables
, Meat
and Cereals
. If the sum of both three go under 100, I've to take the same actions as before.
My old situation was as "John", the only options to which I can evolve my design is to "Fred" or "Paul"?
In which way can I design this? Should I use in addition to neo4j something like MongoDB to represent hierarchy?
Removing the property Food and add the three new properties seems like a bad practices to me. I've to save elsewhere that this 3 means "food"... and what about if in the future will I add others types of foods? Where do I store the knowledge that the value 100 to check, must come from the sum of Meat
, Vegetables
and Cereals
?
Having something like this, will solve my doubt because I can sum all items inside food
:
{
"name": "Lucas",
"food": {
"meat": 40,
"vegetables": 30,
"cereals": 0
}
}
(I don't need to traverse the connections from Food
and Vegetables
to Person
. Just need to check that the sum of Meat, Veg. and Cereals is lesser or greater 100.)
It seems that you are confusing the terms label and property.
According to your diagram, Person
seems to be the label shared by all your nodes, and Name/Food//Meat/Vegetables/Cererals
seem to be the names of node properties.
If my understanding is correct, then there are many approaches to handling multiple food type amounts, and getting a total per person. Below are a couple of examples.
Here is one approach. You could introduce the
Food
label for unique food type nodes:(:Food {type: 'Meat'}), (:Food {type: 'Vegetable'}), etc.
and each
Person
node can have aHAS_FOOD
relationship (with anamount
property) to each relevant Food node (instead of storing the food type properties internally):(john:Person {Name: 'John'})-[:HAS_FOOD {amount: 140}]->(meat:Food {type: 'Meat'})
With this data model, to find all
Person
s with more than 100 units of food:MATCH (p:Person)-[r:HAS_FOOD]->() WITH p, SUM(r.amount) AS total WHERE total > 100 RETURN p;
Here is another approach (which will likely result in faster searches). Since a neo4j property cannot have a map value (contrary to what you show in the JSON near the bottom of your question), each
Person
node could haveamount
andfood
arrays, like this:(:Person {Name: 'Fred', amount: [50, 100], food: ['Meat','Vegetables']})
With this data model, to find all
Person
s with more than 100 units of food:MATCH (p:Person) WHERE REDUCE(s = 0, a IN p.amount | s + a) > 100 RETURN p;
[UPDATE]
However, doing food processing (nice pun, here), with second approach can be more cumbersome and less efficient. For example, this is one way to get the amount of Meat for
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;
And, to set the amount of Meat for
Fred
to 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]];
So, here is a 3rd approach that solves your issue AND is much better for performing food processing. Each Person node could store food amounts directly as properties, like this:
(:Person {Name: 'Fred', Meat: 50, Vegetables: 100, foodNames: ['Meat', 'Vegetables']})
With this data model, the
foodNames
array allows you to iterate through the food properties by name. So, to find all Persons with more than 100 units of food:MATCH (p:Person) WHERE REDUCE(s = 0, n IN p.foodNames | s + p[n]) > 100 RETURN p;
And, to get the amount of Meat for
Fred
:MATCH (p:Person {Name: 'Fred'}) RETURN p.Meat AS meatAmt;
To set the amount of Meat for
Fred
to 123:MATCH (p:Person {Name: 'Fred'}) SET p.Meat = 123;
这篇关于图数据库中的层次结构属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!