Базы данных: Neo4j
Neo4j — графовая база данных. В графовых базах данных объекты хранятся в виде узлов и связей между узлами. Объекты могут содержать данные, их можно представить в виде JSON объекта.
Запуск
Запустить Neo4J проще всего через docker.
docker run \
--name neo4j \
--publish=7474:7474 --publish=7687:7687 \
--volume=$HOME/neo4j/data:/data \
--env=NEO4J_AUTH=none \
-d \
neo4j
Порт 7374
будет работать как HTTP API, а порт 7687
для Bolt API.
Neo4j Browser
После запуска контейнера docker по адресу http://localhost:7474/
будет доступен браузер.
Язык запросов
Neo4J использует язык Cypher для запросов к базе данных. Cypher похож на SQL и предоставляет дополнительные возможности для выборки и изменения графов. Cypher декларативный язык которые описывает, что нужно вернуть, а не как базе данных нужно выбрать данные, это совпадает с SQL. Отличия Cypher в меньших возможностях проверки схемы данных.
Пример запроса на SQL и аналогичного в Cypher:
SELECT movie.name
FROM movie
WHERE movie.rating > 7
MATCH (movie:Movie)
WHERE movie.rating > 7
RETURN movie.title
Следующие примеры с использованием механизма сравнения шаблонов. Cypher позволяет избавится от соединений (join).
SELECT actors.name
FROM actors
LEFT JOIN acted_in ON acted_in.actor_id = actors.id
LEFT JOIN movies ON movies.id = acted_in.movie_id
WHERE movies.title = "The Matrix"
MATCH (actor:Actor)-[:ACTED_IN]->(movie:Movie {title: 'The Matrix'})
RETURN actor.name
Пример на Python
Пример использования библиотеки neo4j (GitHub):
from neo4j import GraphDatabase, RoutingControl
URI = "neo4j://localhost:7687"
def add_friend(driver, name, friend_name):
driver.execute_query(
"MERGE (a:Person {name: $name}) "
"MERGE (friend:Person {name: $friend_name}) "
"MERGE (a)-[:KNOWS]->(friend)",
name=name, friend_name=friend_name, database_="neo4j",
)
def print_friends(driver, name):
records, _, _ = driver.execute_query(
"MATCH (a:Person)-[:KNOWS]->(friend) WHERE a.name = $name "
"RETURN friend.name ORDER BY friend.name",
name=name, database_="neo4j", routing_=RoutingControl.READ,
)
for record in records:
print(record["friend.name"])
with GraphDatabase.driver(URI) as driver:
add_friend(driver, "Arthur", "Guinevere")
add_friend(driver, "Arthur", "Lancelot")
add_friend(driver, "Arthur", "Merlin")
print_friends(driver, "Arthur")
# Guinevere
# Lancelot
# Merlin