Подтвердить что ты не робот

Как моделировать отношения реального мира в базе данных графов (например, Neo4j)?

У меня есть общий вопрос о моделировании в базе данных графа, которую я просто не могу обернуть вокруг.

Как вы моделируете этот тип отношений: "Ньютон изобрел Исчисление"?

В простой график вы можете моделировать его следующим образом:

Newton (node) -> invented (relationship) -> Calculus (node)

... поэтому у вас будет куча "изобретенных" графических связей, поскольку вы добавили больше людей и изобретений.

Проблема заключается в том, что вам нужно добавить кучу свойств в отношение:

  • invention_date
  • influential_concepts
  • influential_people
  • books_inventor_wrote

... и вы захотите начать создавать отношения между этими свойствами и другими узлами, например:

  • influential_people: отношение к узлам пользователя
  • books_inventor_wrote: отношение к книжным узлам

Итак, похоже, что "реальные отношения" ( "изобретенные" ) должны быть node на графике, а график должен выглядеть так:

Newton (node) -> (relationship) -> Invention of Calculus (node) -> (relationship) -> Calculus (node)

И чтобы усложнить ситуацию, другие люди также участвуют в изобретении Исчисления, поэтому график теперь становится чем-то вроде:

Newton (node) -> 
  (relationship) -> 
    Newton Calculus Invention (node) -> 
      (relationship) -> 
        Invention of Calculus (node) -> 
          (relationship) -> 
            Calculus (node)
Leibniz (node) -> 
  (relationship) -> 
    Leibniz Calculus Invention (node) -> 
      (relationship) -> 
        Invention of Calculus (node) -> 
          (relationship) -> 
            Calculus (node)

Итак, я задаю вопрос, потому что кажется, что вы не хотите устанавливать свойства в объектах "отношений" фактической базы данных графа, потому что в какой-то момент вам может понадобиться рассматривать их как узлы в графике.

Правильно ли это?

Я изучал Freebase Metaweb Architecture, и они, кажется, рассматривают все как node. Например, у Freebase есть идея Mediator/CVT, где вы можете создать "Производительность" node, которая связывает "Актер", node к фильму node, как здесь: http://www.freebase.com/edit/topic/en/the_last_samurai. Не совсем уверен, что это одна и та же проблема.

Каковы некоторые руководящие принципы, которые вы используете, чтобы выяснить, действительно ли "отношения реального мира" должны быть графом node, а не отношением графа?

Если есть хорошие книги по этой теме, я бы с удовольствием узнал. Спасибо!

4b9b3361

Ответ 1

Некоторые из этих вещей, такие как invention_date, могут быть сохранены как свойства на ребрах, так как в большинстве графовых баз ребра могут иметь свойства так же, как вершины могут иметь свойства. Например, вы можете сделать что-то вроде этого (код следует TinkerPop Blueprints):

Graph graph = new Neo4jGraph("/tmp/my_graph");
Vertex newton = graph.addVertex(null);
newton.setProperty("given_name", "Isaac");
newton.setProperty("surname", "Newton");
newton.setProperty("birth_year", 1643); // use Gregorian dates...
newton.setProperty("type", "PERSON");

Vertex calculus = graph.addVertex(null);
calculus.setProperty("type", "KNOWLEDGE");

Edge newton_calculus = graph.addEdge(null, newton, calculus, "DISCOVERED");
newton_calculus.setProperty("year", 1666);   

Теперь давайте немного расширим его и добавим в Liebniz:

Vertex liebniz = graph.addVertex(null);
liebniz.setProperty("given_name", "Gottfried");
liebniz.setProperty("surnam", "Liebniz");
liebniz.setProperty("birth_year", "1646");
liebniz.setProperty("type", "PERSON");

Edge liebniz_calculus = graph.addEdge(null, liebniz, calculus, "DISCOVERED");
liebniz_calculus.setProperty("year", 1674);

Добавление в книги:

Vertex principia = graph.addVertex(null);
principia.setProperty("title", "Philosophiæ Naturalis Principia Mathematica");
principia.setProperty("year_first_published", 1687);
Edge newton_principia = graph.addEdge(null, newton, principia, "AUTHOR");
Edge principia_calculus = graph.addEdge(null, principia, calculus, "SUBJECT");

Чтобы узнать все книги, которые Ньютон написал о найденных им вещах, мы можем построить обход графа. Мы начинаем с Ньютона, следим за его ссылками на все, что он обнаружил, а затем переходите по ссылкам в обратном порядке, чтобы получить книги по этому предмету и снова переходите по ссылке, чтобы получить автора. Если автором является Ньютон, вернитесь к книге и верните результат. Этот запрос написан на Gremlin, Groovy языке, специфичном для домена, для обхода графика:

newton.out("DISCOVERED").in("SUBJECT").as("book").in("AUTHOR").filter{it == newton}.back("book").title.unique()

Таким образом, я надеюсь, что немного показал, как можно использовать умный обход, чтобы избежать проблем с созданием промежуточных узлов для представления ребер. В небольшой базе данных это не имеет большого значения, но в большой базе данных вы будете испытывать большие хиты производительности, делая это.

Да, грустно, что вы не можете связывать ребра с другими ребрами в графе, но это ограничение структур данных этих баз данных. Иногда имеет смысл сделать все node, например, в Mediator/CVT, производительность также немного более конкретна. Лица, возможно, пожелают адресовать только выступление Тома Круза в "Последнем самурае" в обзоре. Однако для большинства графических баз я обнаружил, что приложение некоторых графических обходов может получить от меня то, что я хочу из базы данных.