Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

lab3

.pdf
Скачиваний:
0
Добавлен:
19.01.2026
Размер:
1.62 Mб
Скачать

try:

# Подключение к базе данных Neo4j

with GraphDatabase.driver(NEO4J_URI, auth=(NEO4J_USERNAME, NEO4J_PASSWORD)) as driver:

with driver.session(database=NEO4J_DBNAME) as session:

# Очистка базы данных

clear_db(session)

# Заполнение БД create_cars_by_query(session) create_customers_by_query(session) create_sellers_by_query(session) create_orders_by_query(session) session.execute_write(create_relationships)

except Exception as e: print(f"Произошла ошибка: {e}")

# Запуск основной функции if __name__ == "__main__":

main()

Результат выполнения листинга 3 представлен на рисунке 7.

Рисунок 7 - Результат вставки

Листинг 4. Код программы для визуализации результатов запросов import os

from dotenv import load_dotenv from neo4j import GraphDatabase

from prettytable import PrettyTable

# Загрузка переменных окружения

load_dotenv()

# Получение учетных данных Neo4j из переменных окружения

NEO4J_URI = os.getenv("NEO4J_URI")

NEO4J_USERNAME = os.getenv("NEO4J_USERNAME")

NEO4J_PASSWORD = os.getenv("NEO4J_PASSWORD")

NEO4J_DBNAME = os.getenv("NEO4J_DBNAME")

# Нахождение всех автомобилей бренда Audi def func1(session):

query = """

MATCH (c:Car) WHERE c.brand = 'Audi' RETURN c.id as Id, c.model as Model

"""

cars = session.run(query) print("\nВсе авто бренда Audi:")

cars_table = PrettyTable()

cars_table.field_names = [ "ID автомобиля", "Модель автомобиля",

]

for car in cars: cars_table.add_row(

[

car["Id"], car["Model"]

]

)

print(cars_table)

# Нахождение продавцов с зарплатой больше 55 тысяч рублей def func2(session):

query = """

MATCH (s:Seller) WHERE s.salary > 55000 RETURN s.full_name as FullName, s.salary as Salary

"""

sellers = session.run(query)

print("\nВсе продавцы с зарплатой > 55000:") sellers_table = PrettyTable()

sellers_table.field_names = [ "ФИО продавца", "Зарплата продавца",

]

for seller in sellers: sellers_table.add_row(

[

seller["FullName"], seller["Salary"]

]

)

print(sellers_table)

# Получение всех заказов, оплаченных наличными def func3(session):

query = """

MATCH (o:Order) WHERE o.payment_method = 'Наличные' RETURN o.id as OrderId, o.purchase_date as PurchaseDate

"""

orders = session.run(query)

print("\nВсе заказы, оплаченные наличными: ") orders_table = PrettyTable()

orders_table.field_names = [ "Идентификатор заказа", "Дата заказа",

]

for order in orders: orders_table.add_row(

[

order["OrderId"], order["PurchaseDate"]

]

)

print(orders_table)

# Получение всех автомобилей, доступных на складе def func4(session):

query = """

MATCH (c:Car) WHERE c.availability = 'Да' RETURN c.id as Id, c.brand as Brand, c.model as Model

"""

orders = session.run(query)

print("\nПолучение всех автомобилей, доступных на складе: ") orders_table = PrettyTable()

orders_table.field_names = [ "Идентификатор автомобиля", "Бренд автомобиля", "Модель автомобиля"

]

for order in orders: orders_table.add_row(

[

order["Id"], order["Brand"], order["Model"]

]

)

print(orders_table)

# Нахождение всех клиентов, которые совершили покупку автомобиля стоимость свыше 20 тысяч рублей

def func5(session): query = """

MATCH (c:Customer)-[:MADE_ORDER]->(o:Order)-[:INCLUDES_CAR]-

>(car:Car)

WHERE car.price > 20000

RETURN c.full_name AS FullName, car.brand AS Brand, car.model AS

Model

ORDER BY car.price DESC

"""

orders = session.run(query)

print("\nПолучение всех клиентов, купиших автомобили, стоимость которых выше 20000 рублей: ")

orders_table = PrettyTable() orders_table.field_names = [

"ФИО покупателя", "Бренд автомобиля", "Модель автомобиля"

]

for order in orders: orders_table.add_row(

[

order["FullName"], order["Brand"], order["Model"]

]

)

print(orders_table)

# Нахождение продавца, обслужившего больше всего заказов def func6(session):

query = """

MATCH (s:Seller)-[:HANDLED_ORDER]->(o:Order)

RETURN s.full_name AS FullName, COUNT(o) AS NumOrders ORDER BY NumOrders DESC

LIMIT 1

"""

orders = session.run(query)

print("\nПродавец, обслуживший больше всего заказов: ") orders_table = PrettyTable()

orders_table.field_names = [ "ФИО продавца", "Количество заказов",

]

for order in orders: orders_table.add_row(

[

order["FullName"], order["NumOrders"],

]

)

print(orders_table)

# Нахождение всех автомобилей, включенных в заказы за октябрь 2023 def func7(session):

query = """

MATCH (o:Order)-[:INCLUDES_CAR]->(c:Car) WHERE o.purchase_date STARTS WITH '2023-10' RETURN c.brand AS Brand, c.model AS Model ORDER BY c.brand ASC

"""

orders = session.run(query)

print("\nПолучение всех автомобилей, включенных в заказы за октябрь

2023: ")

orders_table = PrettyTable()

orders_table.field_names = [ "Бренд автомобиля", "Модель автомобиля"

]

for order in orders:

orders_table.add_row(

[

order["Brand"], order["Model"]

]

)

print(orders_table)

# Получение общего дохода от продажи автомобилей в октябре 2023 года def func8(session):

query = """

MATCH (o:Order)-[:INCLUDES_CAR]->(c:Car) WHERE o.purchase_date STARTS WITH '2023-10' RETURN SUM(c.price) AS TotalIncome

"""

orders = session.run(query)

print("\nПолучение общего дохода от продажи автомобилей в октябре

2023 года: ")

orders_table = PrettyTable()

orders_table.field_names = [ "Общий доход"

]

for order in orders: orders_table.add_row(

[

order["TotalIncome"]

]

)

print(orders_table)

# Получение страны, автомобили из которой чаще всего покупают. def func9(session):

query = """

MATCH (o:Order)-[:INCLUDES_CAR]->(c:Car)

RETURN c.country AS Country, COUNT(*) AS NumPurchases ORDER BY NumPurchases DESC

LIMIT 1

"""

orders = session.run(query)

print("\nПолучение страны, автомобили из которой чаще всего покупают: ")

orders_table = PrettyTable()

orders_table.field_names = [ "Страна производителя", "Количество автомобилей",

]

for order in orders: orders_table.add_row(

[

order["Country"], order["NumPurchases"],

]

)

print(orders_table)

# Получение покупателя, сделавшего больше всего заказов. def func10(session):

query = """

MATCH (c:Customer)-[:MADE_ORDER]->(o:Order)

RETURN c.full_name AS FullName, COUNT(o) AS NumOrders ORDER BY NumOrders DESC

LIMIT 1

"""

orders = session.run(query)

print("\nПолучение покупателя, сделавшего больше всего заказов: ") orders_table = PrettyTable()

orders_table.field_names = [ "ФИО покупателя",

"Количество сделанныз заказов",

]

for order in orders: orders_table.add_row(

[

order["FullName"], order["NumOrders"],

]

)

print(orders_table)

# Основной блок выполнения def main():

try:

# Подключение к базе данных Neo4j

with GraphDatabase.driver(NEO4J_URI, auth=(NEO4J_USERNAME, NEO4J_PASSWORD)) as driver:

with driver.session(database=NEO4J_DBNAME) as session: func1(session)

func2(session)

func3(session)

func4(session)

func5(session)

func6(session)

func7(session)

func8(session)

func9(session)

func10(session)

except Exception as e: print(f"Произошла ошибка: {e}")

# Запуск основной функции if __name__ == "__main__":

main()

Результаты выполнения запросов представлены на рисунках 8-10.

Рисунок 8 - Результат выполнения

Рисунок 9 - Результат выполнения

Рисунок 10 - Результат выполнения

Вывод

Лабораторная работа посвящена изучению возможностей графовых баз данных,

представленных системой Neo4j, и освоению методов взаимодействия с ней средствами языка программирования Python.

Графовые базы данных отличаются от традиционных реляционных моделей,

представляя данные в виде вершин (узлов) и ребер (связей). Такая структура позволяет легко моделировать сложные взаимосвязи объектов, делая запросы интуитивно понятнее и эффективнее. Интеграция Neo4j с языком Python осуществляется посредством драйвера

GraphDatabase. Использование удобных конструкций, таких как контекстные менеджеры

(with) и генераторы сессий, упрощает написание безопасного и поддерживаемого кода.

При разработке приложений особое внимание уделено вопросам безопасности и удобства сопровождения. Переменные подключения к базе данных вынесены в отдельный конфигурационный файл .env с использованием пакета python-dotenv, что обеспечивает гибкость и безопасность разработки.

Использование Cypher-запросов значительно облегчает процесс формирования и выполнения операций над графовыми структурами. Например, выборка всех автомобилей определенной марки «Audi» выполняется одним простым выражением, демонстрируя эффективность подхода.

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

Проблема:

При попытке использовать конструкцию из листинга 4, возникла ошибка: Expected exactly

one statement per query but got: 30

Листинг 4. Проблемный участок кода

session.run("""

MATCH

(c:Customer {id: 'CLIENT001'}), (o:Order {id: 'ORDER001'})

MERGE (c)-[:MADE_ORDER]->(o);

MATCH (c:Customer {id: 'CLIENT002'}), (o:Order {id: 'ORDER002'})

MERGE

(c)-[:MADE_ORDER]->(o);

Решение:

Проблема, возникшая в представленном фрагменте кода, связана с нарушением синтаксического правила языка запросов Cypher, используемого в графовом хранилище данных Neo4j. Согласно спецификации, запросы к серверу Neo4j допускают выполнение ровно одной операции на одну сессионную команду. Для устранения ошибки достаточно разделить весь объем выполняемых команд на отдельные части и последовательно передавать каждую операцию на выполнение по отдельности. Обновленная версия представлена в листинге 5. Таким образом, каждое действие теперь передается отдельной командой, позволяя правильно исполнить все нужные изменения базы данных.

Листинг 5. Код с решение проблемы from neo4j import GraphDatabase

# Подключаемся к БД

driver = GraphDatabase.driver("bolt://localhost:7687", auth=("neo4j", "password"))

def create_relationships(tx):

# Устанавливаем связь MADE_ORDER между клиентом и заказом tx.run("MATCH (c:Customer {id: 'CLIENT001'}), (o:Order {id:

'ORDER001'}) "

"MERGE (c)-[:MADE_ORDER]->(o)")

tx.run("MATCH (c:Customer {id: 'CLIENT002'}), (o:Order {id: 'ORDER002'}) "

"MERGE (c)-[:MADE_ORDER]->(o)")

...

#Аналогично устанавливаем остальные связи между остальными парами клиентов-заказов,

#продавцов-заказов и заказов-автомобилей

with driver.session() as session: session.write_transaction(create_relationships)

...

Соседние файлы в предмете Программная инженерия