1. введение
Эта статья посвящена Neo4j – одной из самых зрелых и полнофункциональных графовых баз данных на современном рынке. Графовые базы данных подходят к задаче моделирования данных с учетом того, что многие вещи в жизни поддаются представлению в виде набора узлов (V) и связей между ними, называемых ребрами (E).
2. Встроенный Neo4j
Самый простой способ начать работу с Neo4j – это использовать встроенную версию, в которой Neo4j работает в той же JVM, что и ваше приложение.
Во-первых, нам нужно добавить зависимость Maven:
org.neo4j neo4j 3.4.6
Вы можете проверить эту ссылку , чтобы загрузить последнюю версию.
Далее, давайте создадим фабрику:
GraphDatabaseFactory graphDbFactory = new GraphDatabaseFactory();
Наконец, мы создаем встроенную базу данных:
GraphDatabaseService graphDb = graphDbFactory.newEmbeddedDatabase( new File("data/cars"));
Теперь может начаться настоящее действие! Во-первых, нам нужно создать несколько узлов в нашем графике, и для этого нам нужно запустить транзакцию, так как Neo4j отклонит любую разрушительную операцию, если транзакция не была запущена:
graphDb.beginTx();
Как только мы завершим транзакцию, мы сможем начать добавлять узлы:
Node car = graphDb.createNode(Label.label("Car")); car.setProperty("make", "tesla"); car.setProperty("model", "model3"); Node owner = graphDb.createNode(Label.label("Person")); owner.setProperty("firstName", "baeldung"); owner.setProperty("lastName", "baeldung");
Здесь мы добавили заметку Card со свойствами make и model , а также узел Person со свойствами FirstName и LastName
Теперь мы можем добавить отношения:
owner.createRelationshipTo(car, RelationshipType.withName("owner"));
В приведенном выше операторе добавлено ребро, соединяющее два узла с меткой owner . Мы можем проверить эту связь, выполнив запрос, написанный на языке Neo4j powerful Cypher :
Result result = graphDb.execute( "MATCH (c:Car) <-[owner]- (p:Person) " + "WHERE c.make = 'tesla'" + "RETURN p.firstName, p.lastName");
Здесь мы просим найти владельца автомобиля для любого автомобиля марки tesla и вернуть нам его имя и фамилию. Неудивительно, что это возвращает: {p.FirstName=baeldung,}
3. Язык запросов Cypher
Neo4j предоставляет очень мощный и довольно интуитивно понятный язык запросов, который поддерживает полный спектр функций, которые можно было бы ожидать от базы данных. Давайте рассмотрим, как мы можем выполнить эти стандартные задачи создания, извлечения, обновления и удаления.
3.1. Создание узла
Ключевое слово Create можно использовать для создания как узлов, так и связей.
CREATE (self:Company {name:"Baeldung"}) RETURN self
Здесь мы создали компанию с одним свойством имя . Определение узла помечено круглыми скобками, а его свойства заключены в фигурные скобки. В этом случае self является псевдонимом узла, а Company – меткой узла.
3.2. Создание Отношений
Можно создать узел и связь с этим узлом в одном запросе:
Result result = graphDb.execute( "CREATE (baeldung:Company {name:\"Baeldung\"}) " + "-[:owns]-> (tesla:Car {make: 'tesla', model: 'modelX'})" + "RETURN baeldung, tesla");
Здесь мы создали узлы baeldung и tesla и установили отношения собственности между ними. Создание связей с уже существующими узлами, конечно, также возможно.
3.3. Извлечение Данных
Ключевое слово MATCH используется для поиска данных в сочетании с RETURN , чтобы контролировать, какие точки данных возвращаются. Предложение WHERE можно использовать для фильтрации только тех узлов, которые имеют нужные нам свойства.
Давайте выясним название компании, которой принадлежит tesla model X:
Result result = graphDb.execute( "MATCH (company:Company)-[:owns]-> (car:Car)" + "WHERE car.make='tesla' and car.model='modelX'" + "RETURN company.name");
3.4. Обновление узлов
Ключевое слово SET можно использовать для обновления свойств узлов или меток. Давайте добавим пробег к нашей тесле:
Result result = graphDb.execute("MATCH (car:Car)" + "WHERE car.make='tesla'" + " SET car.milage=120" + " SET car :Car:Electro" + " SET car.model=NULL" + " RETURN car");
Здесь мы добавляем новое свойство под названием milage , изменяем метки на Car и Electro и, наконец, полностью удаляем свойство model .
3.5. Удаление узлов
Ключевое слово DELETE можно использовать для постоянного удаления узлов или связей из графика:
graphDb.execute("MATCH (company:Company)" + " WHERE company.name='Baeldung'" + " DELETE company");
Здесь мы удалили компанию под названием Baeldung.
3.6. Привязка параметров
В приведенных выше примерах у нас есть жестко закодированные значения параметров, что не является лучшей практикой. К счастью, Neo4j предоставляет возможность привязки переменных к запросу:
Mapparams = new HashMap<>(); params.put("name", "baeldung"); params.put("make", "tesla"); params.put("model", "modelS"); Result result = graphDb.execute("CREATE (baeldung:Company {name:$name}) " + "-[:owns]-> (tesla:Car {make: $make, model: $model})" + "RETURN baeldung, tesla", params);
4. Драйвер Java
До сих пор мы рассматривали взаимодействие со встроенным экземпляром Neo4j , однако, по всей вероятности, для производства мы хотели бы запустить автономный сервер и подключиться к нему через предоставленный драйвер. Во-первых, нам нужно добавить еще одну зависимость в ваш maven pom.xml :
org.neo4j.driver neo4j-java-driver 1.6.2
Вы можете перейти по этой ссылке , чтобы проверить наличие последней версии этого драйвера.
Теперь мы можем установить связь:
Driver driver = GraphDatabase.driver( "bolt://localhost:7687", AuthTokens.basic("neo4j", "12345"));
Затем создайте сеанс:
Session session = driver.session();
Наконец, мы можем выполнить некоторые запросы:
session.run("CREATE (baeldung:Company {name:\"Baeldung\"}) " + "-[:owns]-> (tesla:Car {make: 'tesla', model: 'modelX'})" + "RETURN baeldung, tesla");
Как только мы закончим со всей нашей работой, нам нужно закрыть как сессию, так и водителя:
session.close(); driver.close();
5. Драйвер JDBC
Также возможно взаимодействие с Neo4j через драйвер JDBC. Еще одна зависимость для наших pom.xml :
org.neo4j neo4j-jdbc-driver 3.4.0
Вы можете перейти по этой ссылке , чтобы загрузить последнюю версию этого драйвера.
Далее, давайте установим соединение JDBC:
Connection con = DriverManager.getConnection( "jdbc:neo4j:bolt://localhost/?user=neo4j,password=12345,scheme=basic");
Здесь con – это обычное соединение JDBC, которое можно использовать для создания и выполнения операторов или подготовленных операторов:
try (Statement stmt = con. stmt.execute("CREATE (baeldung:Company {name:\"Baeldung\"}) " + "-[:owns]-> (tesla:Car {make: 'tesla', model: 'modelX'})" + "RETURN baeldung, tesla") ResultSet rs = stmt.executeQuery( "MATCH (company:Company)-[:owns]-> (car:Car)" + "WHERE car.make='tesla' and car.model='modelX'" + "RETURN company.name"); while (rs.next()) { rs.getString("company.name"); } }
6. Объект-Граф-Отображение
Объектно-графическое отображение или OGM-это метод, который позволяет нам использовать наши доменные POJOS в качестве сущностей в базе данных Neo4j . Давайте рассмотрим, как это работает. Первым шагом, как обычно, мы добавляем новые зависимости в ваш pom.xml :
org.neo4j neo4j-ogm-core 3.1.2 org.neo4j neo4j-ogm-embedded-driver 3.1.2
Вы можете проверить ссылку OGM Core и ссылку OGM Embedded Driver , чтобы проверить наличие последних версий этих библиотек.
Во-вторых, мы аннотируем наши POJO аннотациями OGM:
@NodeEntity public class Company { private Long id; private String name; @Relationship(type="owns") private Car car; } @NodeEntity public class Car { private Long id; private String make; @Relationship(direction = "INCOMING") private Company company; }
@NodeEntity сообщает Neo4j , что этот объект должен быть представлен узлом в результирующем графике. @Relationship сообщает о необходимости создания связи с узлом, представляющим связанный тип. В этом случае компания владеет автомобилем .
Обратите внимание, что Neo4j требует, чтобы у каждой сущности был первичный ключ, а поле с именем id выбирается по умолчанию. Альтернативно именованное поле можно использовать, аннотируя его с помощью @Id @GeneratedValue.
Затем нам нужно создать конфигурацию, которая будет использоваться для начальной загрузки OGM Neo4j . Для простоты давайте использовать встроенную базу данных только в памяти:
Configuration conf = new Configuration.Builder().build();
После этого мы инициализируем SessionFactory с помощью созданной нами конфигурации и имени пакета, в котором находятся наши аннотированные POJO:
SessionFactory factory = new SessionFactory(conf, "com.baeldung.graph");
Наконец, мы можем создать Сеанс и начать его использовать:
Session session = factory.openSession(); Car tesla = new Car("tesla", "modelS"); Company baeldung = new Company("baeldung"); baeldung.setCar(tesla); session.save(baeldung);
Здесь мы инициировали сеанс, создали наши POJO и попросили сеанс OGM сохранить их. Neo4j OGM runtime прозрачно преобразует объекты в набор запросов Cypher , которые создают соответствующие узлы и ребра в базе данных.
Если этот процесс кажется знакомым, то это потому, что он есть! Именно так работает JPA, единственная разница заключается в том, переводится ли объект в строки, которые сохраняются в СУБД, или в ряд узлов и ребер, сохраняемых в базе данных графов.
7. Заключение
В этой статье были рассмотрены некоторые основы графо-ориентированной базы данных Neo4j.
Как всегда, код в этой записи полностью доступен на Github .