Как моделировать реальные отношения в графической базе данных (например, Neo4j)? - PullRequest
19 голосов
/ 24 сентября 2011

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

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

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

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

... так что у вас будет куча «изобретенных» графовых отношений, когда вы добавите больше людей и изобретений.

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

  • invention_date
  • influential_concepts
  • influential_people
  • books_inventor_wrote

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

  • influential_people: отношение к личным узлам
  • books_inventor_wrote: отношение к узлам книги

Так что теперь кажется, что «отношения реального мира» («изобретенные») должны быть узлом на графике, и график должен выглядеть следующим образом:

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

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

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

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

Это правильно?

Я изучал Freebase Metaweb Architecture , и они, похоже, рассматривают все как узел. Например, Freebase имеет идею Mediator / CVT , где вы можете создать узел «Performance», который связывает узел «Actor» с узлом «Film», как здесь: http://www.freebase.com/edit/topic/en/the_last_samurai. Не совсем уверен, что это та же проблема.

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

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

1 Ответ

19 голосов
/ 24 сентября 2011

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

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()

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

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

...