图数据库中的层次结构属性 [英] hierarchy property in graph database

查看:168
本文介绍了图数据库中的层次结构属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我开始使用neo4j. 在我的图形数据库中,我有节点Person(请看下面的"John"),其标签为:Name(字符串),Food(正整数).每个Person通过具有值的关系isFriendTo与其他Person连接. 我仅使用图数据库来查找两个人之间的最短加权路径.

此外,每天我都要检查图中的每个节点,如果食物的价值低于100,我会采取一些措施.

现在,经过一些改进,属性Food不足以容纳我的项目.因此,我必须将其拆分为其他三个更具体的属性(正整数):VegetablesMeatCereals.如果这三个总数之和小于100,则我必须采取与以前相同的操作. 我以前的情况是约翰",我可以将设计发展到的唯一选择是弗雷德"还是保罗"?

我可以通过哪种方式设计它?除了neo4j之外,我是否还应该使用MongoDB之类的东西来表示层次结构?

删除属性Food并添加三个新属性对我来说似乎是个坏习惯.我必须在其他地方保存这个3表示食物" ...如果将来我会添加其他类型的食物呢?在哪里存储要检查的值100必须来自MeatVegetablesCereals的总和的知识? 拥有这样的东西,将解决我的疑问,因为我可以对food:

中的所有项求和

{
  "name": "Lucas",
  "food": {
    "meat": 40,
    "vegetables": 30,
    "cereals": 0
  }
}

(我不需要遍历从FoodVegetablesPerson的连接.只需要检查肉类,蔬菜和谷物的总和是否小于或大于100.)

解决方案

似乎您对术语

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;
    

  • 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.

    1. 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 a HAS_FOOD relationship (with an amount 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 Persons 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;
      

    2. 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 have amount and food arrays, like this:

      (:Person {Name: 'Fred', amount: [50, 100], food: ['Meat','Vegetables']})
      

      With this data model, to find all Persons 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]];
      

    3. 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屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆