Статьи

Применение Neo4j: моделирование с использованием данных Spring Neo4j

Применяется Neo4j: моделирование с SDN

Джонас Партнер, Алекса Вукотик и Ники Уоттс, авторы  Neo4j в действии

Платформа Spring Data Neo4j (SDN) была создана, чтобы упростить жизнь таким разработчикам, как вы, которым необходимо работать с моделями доменов на основе POJO с данными, поддерживаемыми Neo4j. Он направлен на то, чтобы справиться и оградить вас от всей низкоуровневой логики слежения и отображения, связанной с чтением и записью сущностей домена в Neo4j и из нее, что позволяет вам сосредоточиться на важном аспекте написания кода, который делает вас (или ваш компания) деньги, а именно, бизнес-логика. В этой статье, основанной на главе 8 Neo4j в действии, авторы объясняют моделирование предметной области с помощью SDN.

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

Ваше путешествие будет следующим:

  1. Определите стандартную объектную модель POJO для представления вашего домена.
  2. Посмотрите, что требуется SDN для преобразования этих POJO в сущности, поддерживаемые Neo4j.
  3. Окунитесь немного глубже в различные элементы моделирования SDN, в том числе:
  • Моделирование сущностей узлов
  • Моделирование отношений сущностей
  • Моделирование отношений между сущностями узла

Напомним, что в этой социальной сети друзья могут дружить друг с другом. Пользователи также могут отмечать фильмы, которые они видели, и оценивать их от одной до пяти звездочек в зависимости от того, насколько они им понравились. Вы собираетесь добавить свойство userId, которое пользователи могут использовать для входа в систему. Это также позволит вам уникально идентифицировать и ссылаться на каждого пользователя. Наконец, вы также добавите возможность для новых пользователей указывать, был ли существующий участник причиной того, что он или она присоединился к системе, то есть был ли он или она кем-то рекомендован во время присоединения. Это может быть использовано, например, для накопления баллов реферером за каждый фильм, оцененный новыми участниками в течение первого месяца, что может привести к бесплатному билету в кино или какой-либо другой выгоде.Рисунок 1 иллюстрирует, что Джон первоначально присоединился к сети, потому что он был передан Дэвидом.

Рисунок 1 Концептуальный обзор социальной сети любителей кино с рефералами

Начальное моделирование домена POJO

Если вы на мгновение игнорируете тот факт, что ваши данные на самом деле хранятся в Neo4j, и просто попытаетесь смоделировать ваш концептуальный домен как POJO, ваша первая попытка может выглядеть примерно так, как показано в следующем листинге.

Начальная попытка моделирования POJO перечисления 1

public class User {
     String userId;
	String name;
	Set friends;        					#1
	Set views;       					#A
	User referredBy;          					#2
} 

public class Movie {
	String title;
	Set views;       					#B
} 

public class Viewing {
	User user;
	Movie movie;
	Integer stars;							#C
}

# 1 Все друзья пользователя; геттеры, сеттеры и конструкторы опущены для краткости
#A Все просмотры фильмов (со звездами), которые выполнял пользователь
# 2 Пользователь, который направил этого пользователя в систему
#B Все пользователи, которые смотрели этот фильм (со звездами)
#C Рейтинг (от одной до пяти звезд), который пользователь дал за связанный фильм

Здесь нет ничего слишком сложного — это базовое моделирование объектов. Концепции «Пользователь» и «Фильм» были смоделированы как первоклассные объекты, которые кажутся достаточно разумными. Вы также смоделировали просмотр пользователем определенного фильма как объекта, а именно, класса Просмотр. Это связано прежде всего с тем, что в самих отношениях хранится некоторая важная информация, которую вы хотите сохранить и использовать, а именно рейтинг звезд, предоставленный пользователем. Если бы вы смоделировали это как простой тип коллекции отношений между пользователем и фильмом, вы бы потеряли эту информацию.

Обратите внимание, что в этом месте до сих пор нет ссылок на какие-либо SDN- или Neo4j-специфичные концепции, а только на POJO. Затем вам нужно отобразить эту сущность в базовую графовую модель Neo4j. Итак, насколько близко вы подошли к созданию модели POJO, которую легко перенести в ваш мир Neo4j? Вы можете использовать его как есть, или он нуждается в каких-либо модификациях? В этом конкретном случае вы, кажется, хорошо подходите, классы User и Movie аккуратно отображаются в примитивную концепцию узлов Neo4j со связанным свойством name и title соответственно.

Новое отношение referBy (# 2) представляется как ссылка на пользователя, который выполнил ссылку, в то время как отношение IS_FRIEND_OF (# 1) между пользователями хорошо сопоставляется с набором друзей. Кажется, что единственная сложная часть — это моделирование, окружающее класс «Просмотр», который пытается представить сценарий, в котором пользователь посмотрел фильм и по желанию оценил его. Дальнейшая проверка, однако, показывает, что это также идеально вписывается в концепцию отношений Neo4j. Класс Просмотр представляет отношение HAS_SEEN с его необязательным свойством звездочек, а также пользователя, который просматривал фильм, и саму ссылку на фильм.

Все идет нормально; теперь пришло время на самом деле сделать сопоставление с SDN!

ПРИМЕЧАНИЕ.  Не всегда будет возможно найти логическую модель POJO, которая так тесно связана с физической структурой Neo4j. В этом случае вам повезло, но в других случаях вам, возможно, придется адаптировать вашу модель, чтобы она подходила по мере необходимости. В любом случае, он подчеркивает, как общие концепции моделирования POJO действительно относительно хорошо транслируются в структуры Neo4j.

Аннотирование доменной модели

SDN — это библиотека отображения графов объектов на основе аннотаций. Это означает, что это библиотека, которая полагается на способность распознавать определенные SDN-специфичные аннотации, разбросанные по всему коду. Эти аннотации затем обрабатываются как фрагменты информации (то есть метаданные) с инструкциями о том, как преобразовать различные части кода, к которым они присоединены, в их основную структуру в графе. Иногда вы можете даже обнаружить, что вам не нужно комментировать определенные фрагменты кода. Это связано с тем, что в таких случаях SDN пытается определить некоторые разумные значения по умолчанию, применяя принцип соглашения над конфигурацией. Таким образом, отображение графов объектов — это графики, которые ORM для СУБД

Следующий листинг показывает следующий шаг в процессе, когда различные комментарии SDN были добавлены в POJO, чтобы идентифицировать их как объекты, поддерживаемые Neo4j.

Модель домена SDN перечисления 2

@NodeEntity          							#A 
public class User {
    
    String name;								#B
    @Indexed									#B
    @GraphProperty							     #B, #C
    String userId;								#B

    @GraphId									#D
    Long nodeId;								#D

    User referredBy;						   	#E
    @RelatedTo(type = "IS_FRIEND_OF", direction = Direction.BOTH)   	#E
    Set friends;						   	#E
    @RelatedToVia							   	#E
    	Set views;						        #E
}

@NodeEntity     		     						#A 
public class Movie {
    
    String title;								#B
    @GraphId									#D
    Long nodeId;								#D

@RelatedToVia(direction = Direction.INCOMING)			#E
Iterable views; 						#E
}

@RelationshipEntity(type = "HAS_SEEN")    					#F
public class Viewing {

    Integer stars;								#G
    @GraphId									#H
    Long relationshipId;							#H

    @StartNode								#I
    User user;								#I
    @EndNode									#I
    Movie movie;							        #I
}

#A Сопоставляется с узлом Neo4j
#B Хранится как свойства узла в графе (где аннотации отсутствуют, SDN предполагает, что имя поля Java будет таким же, как и у свойства, хранящегося в узле) 
#C Необязательная аннотация, указывающая, что это свойство узла
#D ID узла Neo4j #E
Отношения с другими объектами узла, включающими этот узел (где аннотации отсутствуют, SDN предполагает, что имя поля Java будет таким же, как и у сохраненного отношения)
#F Отобразится в отношение Neo4j #G
Сохранено как свойства отношения в graph #H
ID отношения Neo4j
#I Ссылки на сущности узлов по обе стороны отношения

Эти аннотации, а также разумные значения по умолчанию, принятые SDN на основе имен полей и т. Д., Напрямую связывают элементы вашего Java-класса с физическими объектами в Neo4j. Это означает, что при моделировании с использованием SDN необходимо, чтобы вы хорошо понимали модель данных Neo4j. Хотя SDN оградит вас от необходимости выполнять фактические низкоуровневые отображения самостоятельно, он ожидает, что вы сможете описать, как это должно быть сделано!

В следующих разделах немного разбит листинг 2 и более подробно объясняются некоторые основные концепции моделирования. Мы будем покрывать:

  • Моделирование сущностей узлов
  • Моделирование отношений сущностей
  • Моделирование отношений между сущностями узла

Моделирование сущностей узлов

В SDN объектный узел относится к классу Java, который используется для представления конкретного объекта домена, который в конечном счете представлен и поддерживается примитивом узла Neo4j в базовой базе данных графа. На рисунке 8.2 показаны некоторые узлы-кандидаты в модели домена вашей социальной сети, которые можно смоделировать как объекты узлов SDN.

Рисунок 2 Модель социальной сети с выделенными узлами

Классы Movie и User являются прекрасными примерами здесь. Аннотация @NodeEntity используется, чтобы пометить класс как сущность узла, как правило, помещается непосредственно перед определением класса Java, как показано в листинге 2 и в следующем фрагменте:

@NodeEntity 						#A         	
public class User { 

    String name; 					#1 
    
    @Indexed                                      #2
    @GraphProperty                                #3            
    String userId;                                #3
    @GraphId						#4
    Long nodeId;                                  #4
    . . .
}

#A Cass, поддерживаемый узлом Neo4j
# 1 Сопоставляется с именем свойства на базовом узле
# 2 Гарантирует, что поле userId проиндексировано
# 3 Необязательная аннотация, сопоставляется со свойством userId на базовом узле
# 4 Свойство, содержащее идентификатор узла Neo4j

свойства

В классе, аннотированном @NodeEntity, по умолчанию SDN будет обрабатывать все простые поля как представительные для свойств Neo4j на узле поддержки. В этом контексте простой — это любой примитив или связанный с ним класс-оболочка, строки или объекты, которые можно преобразовать в строку с помощью службы преобразования Spring. Коллекции любого из этих ранее упомянутых типов также включены, где эти коллекции в конечном итоге хранятся в виде массива на узле Neo4j. В предыдущем примере домена это означает, что поля имени (# 1) и заголовка, определенные в классах User и Movie, соответственно, будут сопоставлены как свойства Neo4j с теми же именами без необходимости поднимать палец! Сказав это, вы можете при желании аннотировать поля с @GraphProperty, если вы хотите быть более явным (как вы ‘мы сделали с полем userId в # 3); однако это не является строго необходимым.

А как насчет пользовательских типов свойств?
Базовая среда Spring поставляется с общей системой преобразования типов, которая позволяет вам писать и регистрировать пользовательскую логику преобразования типов, которая может преобразовывать определенный (не примитивный) класс в строковое представление и обратно. SDN уже зарегистрировала некоторые службы конвертации для вас, которые обрабатывают перечисления и даты. Так, если, например, вы определили поле java.util.Date в сущности узла, когда сущность должна быть сохранена, Spring распознает, что существует специальный преобразователь, определенный для полей даты, и использует его для преобразования свойства Date в строка, которая затем сохраняется в графе; обратное происходит при чтении данных из графика и обратно в поле сущности узла.

Это означает, что вы можете воспользоваться этим же механизмом для обработки любых пользовательских типов классов, которые вы, возможно, захотите использовать, например, объект номера телефона. Вам нужно будет написать собственный конвертер, а затем зарегистрировать этот конвертер в Spring. Для получения более подробной информации о том, как это сделать, см. Http://static.springsource.org/spring/docs/current/spring-framework-reference/html/validation.html#core-convert.

Обратите внимание, что если вы не зарегистрируете конвертер, SDN все равно сохранит строковую версию вашего объекта в базе данных, однако она будет просто основана на том, что возвращается из метода toString ().

Теперь вы, вероятно, заметили, что дополнительное поле, похоже, попало в сущности узла User и Movie, а именно nodeId, помеченное @GraphId. Это обязательное требование SDN при использовании простого сопоставления объектов. Пока не вдаваясь в подробности, простое сопоставление объектов является одной из стратегий, используемых SDN для выполнения физического сопоставления между сущностью вашего домена и сущностью поддерживаемого графа. Используя эту стратегию, SDN должен иметь поле, в котором он может хранить базовый идентификатор узла, поддерживающего объект. Аннотация @GraphId (# 4) служит для пометки поля, которое вы отдали для SDN, чтобы сохранить это значение.

Индексированные свойства

Поскольку обычно считается плохой практикой для приложения полагаться на идентификатор узла Neo4j в качестве внешнего уникального идентификатора объекта, важно иметь возможность иметь какой-то другой способ поиска узла. Добавление аннотации @Indexed (# 2) к полю userId обеспечивает возможность поиска и запросов к этому пользователю на основе этого поля.

Под каким индексным именем хранятся эти аннотированные свойства?
По умолчанию SDN создает точный индекс поиска для каждой сущности под простым (не полностью определенным) именем класса (в данном случае, пользователем). Если вы хотите найти пользователя (скажем, John с идентификатором пользователя john001), используя собственный код, он будет закодирован следующим образом:

    IndexManager indexManager = aGraphDatabaseService.index();        
    Index<Node> userIdIndex = indexManager.forNodes("User");
    IndexHits<Node>indexHits = userIdIndex.get("userId","john001");
    Node johnNode = indexHits.getSingle();

Так что будьте осторожны в том, как вы называете и структурируете свои доменные объекты. Как правило, нежелательно иметь две доменные сущности с одинаковыми именами, даже если они находятся в отдельных пакетах из-за этого поведения индексации по умолчанию. Плохим примером этого может быть наличие одного объекта домена пользователя в «базовом» пакете, а другого — в «административном». Хотя это поведение по умолчанию можно переопределить, установив атрибут indexName в аннотации @Indexed, это может сбить с толку тех, кто не знает об этом, и может привести к непредвиденным результатам, если вы не будете осторожны.

Отношения с другими лицами

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

Моделирование отношений сущностей

Объект отношения — это просто версия отношения объекта узла. Он относится к классу Java, который в конечном итоге представлен и поддерживается отношением Neo4j в базовой базе графов. Neo4j рассматривает отношения как первоклассных граждан, которые, как и узлы, могут иметь свой собственный идентификатор и набор свойств, если это необходимо. Таким образом, SDN также позволяет им быть представленными как объекты самостоятельно.

Рисунок 3 Модель социальной сети с выделенными отношениями, которые потенциально могут быть смоделированы как объекты отношений

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

ПРИМЕЧАНИЕ.  Вероятно, в вашей физической модели Neo4j будет определено много отношений, но это не означает автоматически, что все они должны быть смоделированы как объекты отношений в SDN!

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

Отношение HAS_SEEN — прекрасный пример этого, с его дополнительным свойством звездочек, обеспечивающим больше контекста для отношений, который указывает не только на то, что пользователь видел фильм, но и на то, как он или она могли его оценить. В модели социальной сети это отношение со всей связанной с ним информацией было определено как класс Просмотр, как показано в листинге 3. Сравните это с отношением IS_FRIEND_OF, которое само по себе является всем, что требуется для понимания отношений между двумя пользователями — это в том, что они друзья. На эти отношения простого типа (то есть на отношения IS_FRIEND_OF) все еще можно ссылаться, и вы увидите, как это делается в следующем разделе, но нет никакого дополнительного преимущества в определении целого нового класса для его представления.

Класс просмотра перечисления 3: объект отношения

@RelationshipEntity(type = "HAS_SEEN")	               #A
public class Viewing {
    @GraphId							#1
    Long relationshipId;					#1

    @StartNode						#2
    User user;						#2

    @EndNode							#3
    Movie movie;						#3

    Integer stars; 						#B
}

#A Класс поддерживается отношением Neo4j
# 1 Свойство, содержащее отношение Neo4j ID
# 2 Узел пользователя, из которого возникает отношение (исходящий)
# 3 Узел фильма, на котором заканчивается отношение (входящий)
#B Отображает свойство звездочек на базовом отношении

Аннотация @RelationshipEntity применяется к классам, чтобы указать, что она представляет отношение Neo4j. Аннотация принимает свойство типа, используемое для указания имени типа отношения Neo4j, используемого внутри. Если не указано, имя класса будет считаться физическим именем, используемым в Neo4j. Как и в случае с объектом-узлом, объект-связь имеет те же требования к аннотированному полю @GraphId (# 1), на этот раз для хранения идентификатора базовой взаимосвязи.

Если вы хотите получить доступ к сущностям узла по обе стороны этого отношения, вам нужно предоставить поле для каждого из них и аннотировать их с помощью @StartNode (# 2) и @EndNode (# 3). Для примера класса «Просмотр» сущность узла «Пользователь» начинает (имеет исходящую) связь с конечной сущностью «Фильм»

С точки зрения того, что требуется для моделирования отношений Neo4j, вот и все. Однако, как правило, нет особого смысла в определении классов сущностей отношений в изоляции. На них почти всегда ссылаются через одно или несколько полей связанных узловых сущностей. В следующем разделе мы подробно рассмотрим всю область, в которой сущности узлов могут ссылаться на другие сущности узлов, с помощью простых ссылок, а также посредством отношений, смоделированных POJO. Однако, чтобы предоставить полный контекст для этого примера, листинг 4 обеспечивает предварительный просмотр того, как сущность узла пользователя, а также сущность узла фильма, ссылаются на класс сущности отношения просмотра через поле их представлений.

Фрагменты сущности узла и пользователя узла перечисления 4

@NodeEntity
public class User {
    @RelatedToVia								#1
    Set views; 							#1
    . . .

@NodeEntity
public class Movie {
    @RelatedToVia(direction = Direction.INCOMING)    			#2
    Iterable views;                                            #2

# 1 Для каждого отношения HAS_SEEN между пользователем и всеми фильмами, которые он или она просмотрели, класс Просмотр содержит информацию об отношениях
# 2 Для каждого отношения HAS_SEEN между фильмом и всеми пользователями, которые его видели, класс просмотра содержит информацию об отношениях

Внутри сущности узла «Пользователь» аннотация RelatedToVia (# 1) в поле представлений по существу читается как «все отношения HAS_SEEN (со всеми связанными свойствами) между этим пользователем и любыми фильмами, которые он или она смотрели». (Тип отношения HAS_SEEN выводится, потому что это то, что определено в самом классе Просмотр.) Класс Просмотр представляет полный контекст отношений между этими двумя объектами, включая поле рейтинга.

Внутри сущности узла Movie аннотация RelatedToVia (# 2) помечает поле представлений как «все отношения HAS_SEEN (со всеми связанными свойствами) между этим фильмом и любыми пользователями, которые его действительно смотрели».

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

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

Моделирование отношений между сущностями узла

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

Конец предыдущего раздела предоставил предварительный просмотр того, как такое соединение было установлено между объектами «Пользователь» и «Фильм» через объект отношения «Просмотр». Вы видели, как отношения HAS_SEEN между пользователями и фильмами моделировались как физический POJO (класс просмотра), а затем на них ссылались объекты. В этом конкретном случае для представления отношений в контексте использовался целый отдельный класс (просмотр). Но как насчет других, более простых отношений, таких как «Джон — друг Джека»? Вам также нужен выделенный класс сущностей отношений для таких случаев? Вам будет приятно узнать, что ответ — нет, с ними можно справиться гораздо более простым способом. На рисунке 4 показаны отношения между сущностями узлов, на которые вы потенциально можете ссылаться из сущностей узлов.

Рисунок 4 Модель социальной сети с выделенными ссылками на отношения между узлами

С точки зрения сущности узла, отношения также просто моделируются как обычные ссылки на Java-объекты и могут быть разными, в зависимости от того, что именно вы пытаетесь передать. Мы уже предварительно рассмотрели, как вы можете использовать класс Просмотр для ссылки на отношение HAS_SEEN, но давайте рассмотрим и другие более простые отношения, такие как referBy и IS_FRIEND_OF.

Отношения, связанные с сущностями «Пользователь» и «Фильм», показаны в следующем листинге.

Фрагменты сущности узла и пользователя узла перечисления 5

public class User {
    User referredBy;                                                   #1
    @RelatedTo(type = "IS_FRIEND_OF", direction = Direction.BOTH)      #2
    Set friends; 						      #2
    @RelatedToVia                                                      #3
    Set views;                                                #3
    . . .

public class Movie {
    @RelatedToVia(direction = Direction.INCOMING)                      #4
    Iterable views;                                           #4
    . . .

# 1 Пользователь (сущность узла), связанный с этим узлом через отношение
ReferBy # 2 Пользователи (сущности узла), связанные с этим узлом через отношение IS_FRIEND_OF
# 3 Информация о взаимоотношениях (сущность отношения), которая существует между этим пользователем и фильмами (сущностями узла), он или она просматривается через отношение HAS_SEEN
# 4 Информация об отношениях только для чтения (сущность отношения), которая существует между этим фильмом и пользователями (сущностями узла), которые оценили его через отношение HAS_SEEN

Базовые отношения, определенные как представленные нижележащим отношением Neo4j без ассоциированных свойств, точно равному нулю или одному другому объекту узла, могут быть смоделированы как ссылка на стандартный объект в объекте узла. По умолчанию имя свойства будет использоваться в качестве имени для сопоставления с типом отношения в Neo4j при отсутствии какой-либо мета-информации об обратном. Недавно представленная концепция рефералов одного пользователя другому (смоделированная свойством ReferBy в # 1) является отличным примером этого. Обратите внимание, что это свойство должно быть ссылкой на другой объект узла.

Базовые отношения с нулем или несколькими другими объектами узла моделируются либо с помощью класса Set, List, Collection или Iterable, но и с объектом ссылочного узла в качестве типа коллекции. Использование класса Set, List или Collection означает, что поле модифицируемо с точки зрения содержащего узла, в то время как класс Iterable указывает, что это следует рассматривать как доступное только для чтения. На основании типа класса сущности узла и его аннотаций SDN сможет определить, что вы хотите, чтобы это поле представляло базовые отношения. Однако, если вы хотите перезаписать любое из значений по умолчанию, вы можете добавить аннотацию @RelatedTo. Отношения друзей (# 2) между пользователями — пример.Обратите внимание, что в этом случае мы добавили аннотацию @RelatedTo, чтобы указать базовый тип отношения Neo4j как IS_FRIEND_OF, а не значение по умолчанию, которое SDN мог бы вывести, если бы его не было, то есть имя поля, на которое ссылаются, друзья.

Богатые отношения, определяемые как представленные базовыми отношениями Neo4j со связанными свойствами, также моделируются тем же классом Collection, что и базовые отношения. В этом случае, однако, тип содержащегося объекта в коллекции является объектом отношения, а не объектом узла. Напомним, что сущность отношения представляет основную связь Neo4j вместе со всеми связанными свойствами, которые также были смоделированы в этой сущности. Это обеспечивает удобный способ доступа к богатой информации о самой взаимосвязи, в то же время обеспечивая возможность доступа к сущности или сущностям на другом конце. Как и в случае базовых отношений, без каких-либо аннотаций SDN может решить, что вы создаете такие ссылки, основываясь исключительно на том факте, что тип класса, содержащийся в коллекции, был определен как объект отношения. Еще раз,если вы хотите переопределить любое из этих значений по умолчанию для отношений, предполагаемых SDN, вы можете применить аннотацию @RelatedToVia. Как вы уже видели, ссылка на поле представлений (# 3), представляющая отношения между пользователем и фильмом, является хорошим примером здесь, поскольку дополнительный рейтинг звезд служит для улучшения информации об отношениях между этими двумя объектами. Обратите внимание на другой класс Collection, используемый для свойства views в случае узлов User и Movie, а именно Setand Iterable, соответственно. Это означает, что свойство views можно изменить с точки зрения узла User, но не с узла Movie. Концептуально пользователи оценивают фильмы, фильмы не применяют оценки для пользователей!Ссылка на поле просмотров (# 3), представляющая отношения между пользователем и фильмом, является хорошим примером здесь, поскольку дополнительный рейтинг звезд служит для улучшения информации об отношениях между этими двумя объектами. Обратите внимание на другой класс Collection, используемый для свойства views в случае узлов User и Movie, а именно Setand Iterable, соответственно. Это означает, что свойство views можно изменить с точки зрения узла User, но не с узла Movie. Концептуально пользователи оценивают фильмы, фильмы не применяют оценки для пользователей!Ссылка на поле просмотров (# 3), представляющая отношения между пользователем и фильмом, является хорошим примером здесь, поскольку дополнительный рейтинг звезд служит для улучшения информации об отношениях между этими двумя объектами. Обратите внимание на другой класс Collection, используемый для свойства views в случае узлов User и Movie, а именно Setand Iterable, соответственно. Это означает, что свойство views можно изменить с точки зрения узла User, но не с узла Movie. Концептуально пользователи оценивают фильмы, фильмы не применяют оценки для пользователей!Обратите внимание на другой класс Collection, используемый для свойства views в случае узлов User и Movie, а именно Setand Iterable, соответственно. Это означает, что свойство views можно изменить с точки зрения узла User, но не с узла Movie. Концептуально пользователи оценивают фильмы, фильмы не применяют оценки для пользователей!Обратите внимание на другой класс Collection, используемый для свойства views в случае узлов User и Movie, а именно Setand Iterable, соответственно. Это означает, что свойство views можно изменить с точки зрения узла User, но не с узла Movie. Концептуально пользователи оценивают фильмы, фильмы не применяют оценки для пользователей!

Both the @RelatedTo (#3) and @RelatedToVia (#4) annotations can take a type and optional direction element that can be used, specified to clarify whether relationships of a particular direction (valid values are INCOMING, BOTH, and the default OUTGOING) should be included in the collection of entities returned.

Note that for the friends property you need to specify the direction as BOTH as shown in the following snippet:

@RelatedTo(type = "IS_FRIEND_OF", direction = Direction.BOTH)
    Set friends;

Logically, a friends relationship is bidirectional, physically within Neo4j, however, relationships are only stored in one direction. By specifying BOTH you’re telling Neo4j to consider any IS_FRIENDS_OF relationships associated with the user regardless of which direction the physical relationship is defined.

Summary

We introduced you to the Spring Data Neo4j (SDN) framework that provides you with a variety of tools to be able to operate with a standard POJO-based domain model backed by the powerful Neo4j database.

Here are some other Manning titles you might be interested in:

Hadoop in Action
Chuck Lam

Mahout in Action
Sean Owen, Robin Anil, Ted Dunning, and Ellen Friedman

Tika in Action
Chris A. Mattmann and Jukka L. Zitting

Save 50% on Neo4j in ActionMondrian in Action, and CMIS and Apache Chemistry with promo code dzwkd3 only at manning.com. Offer expires midnight, August 1st EST.