этой статьипервая частьВведение в Neo4j и его язык запросов Cypher. Если вы читали часть 1, то поняли, почему Neo4j и другие графовые базы данных особенно популярны.
Затем мы используем язык запросов Cypher для моделирования семьи в Neo4j, включая личные атрибуты, такие как возраст, пол и отношения между членами семьи. Мы создаем несколько друзей, чтобы расширить наш социальный граф, затем добавляем пары ключ/значение, чтобы создать список фильмов, просмотренных каждым пользователем. Наконец, мы запросили наши данные, используя графическую аналитику, чтобы найти фильм, который пользователь не видел, но может ему понравиться.
Язык запросов Cypher отличается от традиционных языков запросов данных, таких как SQL. Вместо того, чтобы думать о таких вещах, как таблицы и отношения внешних ключей, Cypher заставляет вас думать об узлах, естественных отношениях между узлами и различных обходах, которые могут быть выполнены между отдельными отношениями. С помощью Cypher вы можете создать собственную ментальную модель того, как объекты реального мира связаны друг с другом. Требуется некоторая практика, чтобы научиться писать запросы Cypher, но как только вы поймете, как они работают, даже очень сложные запросы обретут смысл.
После моделирования социального графа в Neo4j с использованием языка запросов Cypher и написания запросов с использованием этого социального графа очень просто написать код Java для выполнения запроса на графе. В этой статье вы узнаете, как интегрировать Neo4j с клиентским веб-приложением Java, которое вы можете использовать для запроса социального графа, созданного нами в части 1.
Настройте свой проект Neo4j
Наш первый шаг — создать новый проект Maven:
mvn archetype:generate -DgroupId=com.geekcap.javaworld -DartifactId=neo4j-example -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false
Откройте свойpom.xml
файл и добавьте драйвер Neo4j версии 1.4.1 на момент написания:
<dependency>
<groupId>org.neo4j.driver</groupId>
<artifactId>neo4j-java-driver</artifactId>
<version>1.4.1</version>
</dependency>
Создайте драйвер Neo4j
Затем создайте Neo4jDriver
,Следующее:
Driver driver = GraphDatabase.driver( "bolt://localhost:7687", AuthTokens.basic("neo4j", "neo4j"));
КнигаGraphDatabase
Класс имеет метод, называемый статическимdriver()
принимает URL-адрес для подключения к Neo4j иAuthToken
. Вы можете создать базовуюAuthToken
.
существуетDriver
Облегченное общение с Neo4j. мы запрашиваемDriver
СоздайтеSession
объект для выполнения запроса следующим образом:
Session session = driver.session();
Интерфейс сеанса
Долженorg.neo4j.driver.v1.Session
Интерфейс для выполнения транзакций на Neo4j. В простейшей форме мы можем выполнить унаследованное отrun()
метод. Затем будет запущена транзакция, будет запущен наш оператор, и транзакция будет зафиксирована.Sessionorg.neo4j.driver.v1.StatementRunnerSession
ДолженStatementRunner
Несколько вариантов, определяемых интерфейсомrun()
метод. Это тот, который мы будем использовать:
StatementResult run(String statementTemplate, Map<String,Object> statementParameters)
объявить параметры
ДолженstatementTemplate
это файл, содержащий наш запрос CypherString
,statementParameters
Включите именованные параметры, которые мы будем использовать. Например, мы можем захотеть создатьPerson
:
session.run("CREATE (person: Person {name: {name}, age: {age}})",
parameters("name", person.getName(), "age", person.getAge()));
{name}和{age}
named, который можно решить, передав какString
стоило тогоMap
. каждыйString
Оба содержат имя свойства и должны соответствовать значению в шаблоне. Долженparameters
метод обычно начинается сValues
Статический импорт объекта:
import static org.neo4j.driver.v1.Values.parameters
Управление транзакциями
ОдинSession
После того, как это было сделано, вам нужно вызвать его с помощьюclose()
способ закрыть. Для удобства,Session
объект реализуетjava.lang.AutoCloseable
интерфейс, поэтому, начиная с Java 7, вы можете сделать это в операторе try-with-resources, например:
try (Session session = driver.session()) {
session.run("CREATE (person: Person {name: {name}, age: {age}})",
parameters("name", person.getName(), "age", person.getAge()));
}
Наконец, если вы выполняете несколько операторов, связанных с одной транзакцией, вы можете обойтиSession
изrun()
Методы автоматизированного управления транзакциями и прозрачные самоуправляемые транзакции. Например:
try (Session session = driver.session()) {
try (Transaction tx = session.beginTransaction()) {
tx.run("CREATE (person: Person {name: {name}, age: {age}})",
parameters("name", person.getName(), "age", person.getAge()));
tx.success();
}
}
звонокSession.beginTransaction()
вернутьTransaction
Объект, который можно использовать для запуска операторов Cypher. После выполнения оператора Cypher вы должны вызватьtx.success()
или оператор try-with-resources отменит транзакцию. ДолженTransaction
выполнитьAutoCloseable
. Если транзакция помечена как успешная (вызовомsuccess()
), транзакция зафиксирована, в противном случае транзакция будет отменена. Вы можете сделать это, позвонивTransaction
изfailure()
способ явного отказа транзакции.
объект записи
вы могли наблюдатьSession
а такжеTransaction
в классеrun()
методы возвращаютStatementResult
пример.StatementResult
интерфейс доступенRecord
список,Record
Объекты могут иметь один или несколькоValue
объект.
с JDBC отResultSet
Полученное значение аналогично,Record
Позволяет получить значения по индексу или по имени. вернутьValue
объект может быть вызванNode.asNode()
методы или примитивы (например,String
или целое число), вызывая другиеasXXX()
Один из методов конвертирует в Neo4j. Примеры в предыдущих разделах в основном возвращают узлы, но в последнем примере имя человека принимается какString
вернуть. Вот почемуValue
Объекты Reason обеспечивают гибкость в возвращаемых типах.
Пример приложения на Java
Теперь мы возьмем то, что мы узнали, и создадим пример приложения на Java. на основеПримеры моделирования и запросов в части 1, это приложение создаетPerson
объект, найти всеPerson
объект, найти всех друзейPerson
, и найтиPerson
Все фильмы, которые вы видели.
Листинг 1 и Листинг 2 создают определенияPerson
и класс Java дляMovie
. В листинге 3 показан исходный код нашего тестового класса:Neo4jClient
.
Листинг 1. Person.java
package com.geekcap.javaworld.neo4j.model;
public class Person {
private String name;
private int age;
public Person() {
}
public Person(String name) {
this.name = name;
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
Листинг 2. Movie.java
package com.geekcap.javaworld.neo4j.model;
public class Movie {
private String title;
private int rating;
public Movie() {
}
public Movie(String title) {
this.title = title;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public int getRating() {
return rating;
}
public void setRating(int rating) {
this.rating = rating;
}
}
Листинг 3. Neo4jClient.java
package com.geekcap.javaworld.neo4j;
import com.geekcap.javaworld.neo4j.model.Movie;
import com.geekcap.javaworld.neo4j.model.Person;
import org.neo4j.driver.v1.*;
import org.neo4j.driver.v1.types.Node;
import java.util.HashSet;
import java.util.Set;
import static org.neo4j.driver.v1.Values.parameters;
public class Neo4jClient {
/**
* Neo4j Driver, used to create a session that can execute Cypher queries
*/
private Driver driver;
/**
* Create a new Neo4jClient. Initializes the Neo4j Driver.
*/
public Neo4jClient() {
// Create the Neo4j driver
driver = GraphDatabase.driver( "bolt://localhost:7687", AuthTokens.basic("neo4j", "neo4j"));
}
/**
* Create a new Person.
* @param person The Person to create
*/
public void createPerson(Person person) {
// Create a Neo4j session. Because the Session object is AutoCloseable, we can use a try-with-resources statement
try (Session session = driver.session()) {
// Execute our create Cypher query
session.run("CREATE (person: Person {name: {name}, age: {age}})",
parameters("name", person.getName(), "age", person.getAge()));
}
}
/**
* Finds all Person objects in the Neo4j database.
* @return A set of all Person objects in the Neo4j database.
*/
public Set<Person> findAllPeople() {
// Create a set to hold our people
Set<Person> people = new HashSet<>();
// Create a Neo4j session
try (Session session = driver.session()) {
// Execute our query for all Person nodes
StatementResult result = session.run("MATCH(person:Person) RETURN person");
// Iterate over the response
for (Record record: result.list()) {
// Load the Neo4j node from the record by the name "person", from our RETURN statement above
Node person = record.get("person").asNode();
// Build a new person object and add it to our result set
Person p = new Person();
p.setName(person.get("name").asString());
if (person.containsKey("age")) {
p.setAge(person.get("age").asInt());
}
people.add(p);
}
}
// Return the set of people
return people;
}
/**
* Returns the friends of the requested person.
*
* @param person The person for which to retrieve all friends
* @return A Set that contains all Person objects for which there is a FRIEND relationship from
* the specified person
*/
public Set<Person> findFriends(Person person) {
// A Set to hold our response
Set<Person> friends = new HashSet<>();
// Create a session to Neo4j
try (Session session = driver.session()) {
// Execute our query
StatementResult result = session.run("MATCH (person: Person {name: {name}})-[:FRIEND]-(friend: Person) RETURN friend",
parameters("name", person.getName()));
// Iterate over our response
for (Record record: result.list()) {
// Create a Person
Node node = record.get("friend").asNode();
Person friend = new Person(node.get("name").asString());
// Add the person to the friend set
friends.add(friend);
}
}
// Return the set of friends
return friends;
}
/**
* Find all movies (with rating) seen by the specified Person.
*
* @param person The Person for which to find movies seen
* @return A Set of Movies (with ratings)
*/
public Set<Movie> findMoviesSeenBy(Person person) {
Set<Movie> movies = new HashSet<>();
try (Session session = driver.session()) {
// Execute our query
StatementResult result = session.run("MATCH (person: Person {name: {name}})-[hasSeen:HAS_SEEN]-(movie:Movie) RETURN movie.title, hasSeen.rating",
parameters("name", person.getName()));
// Iterate over our response
for (Record record: result.list()) {
Movie movie = new Movie(record.get("movie.title").asString());
movie.setRating(record.get("hasSeen.rating").asInt());
movies.add(movie);
}
}
return movies;
}
/**
* Helper method that prints a person set to the standard output.
* @param people The set of Person objects to print to the standard output
*/
public static void printPersonSet(Set<Person> people) {
for (Person person: people) {
StringBuilder sb = new StringBuilder("Person: ");
sb.append(person.getName());
if (person.getAge()>0) {
sb.append(" is " + person.getAge() + " years old");
}
System.out.println(sb);
}
}
/**
* Test methods
*/
public static void main(String ... args) {
Neo4jClient client = new Neo4jClient();
client.createPerson(new Person("Duke", 22));
Set<Person> people = client.findAllPeople();
System.out.println("ALL PEOPLE");
printPersonSet(people);
Set<Person> friendsOfMichael = client.findFriends(new Person("Michael"));
System.out.println("FRIENDS OF MICHAEL");
printPersonSet(friendsOfMichael);
Set<Movie> moviesSeenByMichael = client.findMoviesSeenBy(new Person("Michael"));
System.out.println("MOVIES MICHAEL HAS SEEN:");
for (Movie movie: moviesSeenByMichael) {
System.out.println("Michael gave the movie " + movie.getTitle() + " a rating of " + movie.getRating());
}
}
}
Пример приложения: клиентский класс Neo4j
существуетNeo4jClient
Neo4j класс создан в его конструкцииDriver
. затем его метод использованияDriver
создатьSession
объект для выполнения запросов Cypher.createPerson()
Метод выполняет запрос Cypher с именованными параметрами «имя» и «возраст».CREATE (person:Person {...})
.parameters()
метод связывает эти параметры с указаннымPerson
атрибуты имени и возраста.
findAllPeople()
поиск методаPerson
Все объекты в базе. Обратите внимание, что этот метод возвращаетвсе, поэтому, если у вас много людей, вы можете добавить к ответуLIMIT
. Вот пример:
MATCH (person:Person) RETURN person LIMIT 25
В этом случае мы возвращаем полныйPerson
узел, поэтому я начинаю сRecord
получить "человек" и использоватьNoded
изasNode()
метод преобразования.
findFriends()
метод делает то же самое, но выполняет другой запрос Cypher:
MATCH (person: Person {name: {name}})-[:FRIEND]-(friend: Person) RETURN friend
Мы спрашиваем человека с данным именем и ищем этого человекаFRIEND
отношения, найти всеPerson
Узлы, назовите каждый узел «друзьями». Поэтому, когда мы начинаем сRecord
При получении ответа в , мы запрашиваем «друзья» и преобразуем его вNode
.
Наконец,findMoviesSeenBy()
Метод выполняет следующий запрос Cypher:
MATCH (person: Person {name: {name}})-[hasSeen:HAS_SEEN]-(movie:Movie) RETURN movie.title, hasSeen.rating
Этот запрос начинается с назначенного лица и следуетHAS_SEEN
а такжеMovie
Все отношения узла. Затем он возвращает атрибут названия фильмаmovie.title
и оценивается какhasSeen.rating
.
Чтобы сделать это, мы должныHAS_SEEN
Укажите имя переменной в отношенииhasSeen
. Поскольку мы запрашиваем названия фильмов и рейтинги, мы получаем из следующихRecord:
:
record.get("movie.title").asString()
record.get("hasSeen.rating").asInt()
Долженmain()
метод создания новогоNeo4jClient
, создайте 22-летнего человека по имени «Герцог» (подсказка: точно так же, как Java)Person
. Он находит друзей Майкла и фильмы, которые он видел.
В листинге 4 показан Mavenpom.xml
файл, который мы используем для сборки и запуска нашего приложения.
Листинг 4. Maven POM для приложения Neo4jClient
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.geekcap.javaworld</groupId>
<artifactId>neo4j-example</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>neo4j-example</name>
<url>http://maven.apache.org</url>
<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!-- Import Neo4j -->
<dependency>
<groupId>org.neo4j.driver</groupId>
<artifactId>neo4j-java-driver</artifactId>
<version>1.4.1</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.0.2</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
<mainClass>com.geekcap.javaworld.neo4j.Neo4jClient</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy</id>
<phase>install</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/lib</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Этот файл pom.xml импортируетneo4j-java-driver
зависимости, затем определите три плагина:
- maven-compiler-pluginУстановите версию сборки Java на 1.8.
-
maven-jar-pluginСделайте основной класс установленным в исполняемый файл JAR,
com.geekcap.javaworld.neo4j.Neo4jClient
и содержитlib
Все файлы в каталоге файлов JARCLASSPATH
. -
maven-dependency-plugin будетСкопируйте все зависимости в каталог сборки проекта.
lib
папка.
Создайте и запустите клиентское приложение Neo4j.
Теперь вы можете создать клиентское приложение Neo4j с помощью:
mvn clean install
ты сможешьtarget
Запустите его из каталога с помощью:
java -jar neo4j-example-1.0-SNAPSHOT.jar
Вы должны увидеть вывод, подобный следующему:
ALL PEOPLE
Person: Steven is 45 years old
Person: Jordyn
Person: Michael is 16 years old
Person: Katie
Person: Koby
Person: Duke is 22 years old
Person: Grant
Person: Rebecca is 7 years old
Person: Linda
Person: Charlie is 16 years old
FRIENDS OF MICHAEL
Person: Charlie
Person: Grant
Person: Koby
MOVIES MICHAEL HAS SEEN:
Michael gave movie Avengers a rating of 5
Обязательно перейдите в веб-интерфейс Neo4j и выполните несколько запросов! Вы должны увидеть, как Duke создан, и сможете проверить результат.
Заключение части 2
Neo4j — это графовая база данных для управления тесно связанными данными. Мы начали это исследование с рассмотрения требований к графовым базам данных, особенно при запросе более чем трех степеней разделения в отношениях. После настройки Neo4j в нашей среде разработки мы потратили большую часть времени на изучение языка запросов Neo4j Cypher. Мы построили сеть семейных отношений и запросили эти отношения с помощью Cypher. В этой статье мы сосредоточимся на том, чтобы научиться
Во второй части вы узнали, как написать приложение Java, которое подключается к Neo4j и выполняет запросы Cypher. Мы выбрали самый простой (ручной) способ интеграции Java с Neo4j. После того, как вы освоите основы, вы, возможно, захотите изучитьИнтеграция Java с Neo4jБолее продвинутые подходы, такие как использование библиотеки Neo4j Object Graph Mapping (OGM), Neo4j-OGM и Spring Data.
Для получения дополнительных статей, пожалуйста, посетите: http://www.apexyun.com
Общедоступный номер: Galaxy № 1
Контактный адрес электронной почты: public@space-explore.com
(Пожалуйста, не перепечатывайте без разрешения)