Neo4j
GraphDB はノード(商品・店舗)とエッジ(購入履歴)で関係を管理できるため、例えば「特定の商品をどの店舗で買うべきか」の分析が容易になります。
データの構造(ノードとリレーション)
* ノード
* (:Item {name: “牛乳”})
* (:Store {name: “スーパーA”})
* リレーション
* (:Item)-[:SOLD_AT {price: 198, date: “2025-02-01”}]->(:Store)
Neo4j でのデータ登録
from neo4j import GraphDatabase
uri = "bolt://localhost:7687"
driver = GraphDatabase.driver(uri, auth=("neo4j", "password"))
def add_purchase(tx, item, store, price, date):
query = """
MERGE (i:Item {name: $item})
MERGE (s:Store {name: $store})
CREATE (i)-[:SOLD_AT {price: $price, date: $date}]->(s)
"""
tx.run(query, item=item, store=store, price=price, date=date)
with driver.session() as session:
session.write_transaction(add_purchase, "牛乳", "スーパーA", 198, "2025-02-01")
購入履歴から最適な店舗を検索
MATCH (i:Item {name: "牛乳"})-[r:SOLD_AT]->(s:Store)
RETURN s.name AS store, MIN(r.price) AS lowest_price
SQLite と GraphDB の使い分け
| 機能 | SQLite | GraphDB | | ----------- | --------------- | -------------------- | | データの保存 | 高速・軽量 | 遅め(構造化に向いている) | | 最安値検索 | シンプルな SQL で実装可能 | 関係性を活かした分析が得意 | | データの可視化 | 表形式が得意 | ネットワーク分析が可能 | | セールや価格変動の分析 | やや複雑 | 履歴をノード間リレーションで管理しやすい |
* SQLite: 基本的な購入データ管理(最安値検索・履歴保存)に向いている。
* GraphDB: 「どの店舗でどの商品を買うべきか?」を関係性で分析するのに適している。
まずは SQLite をメインに使用し、分析が必要な部分を GraphDB に移行するのが良さそう
SQLite と Neo4j を組み合わせることは可能
それぞれの役割を明確にし、データの流れを整理すれば、最適な購買管理システムを構築できる
| データ | SQLite | Neo4j | | ----------------- | ------ | -------------- | | 購入履歴(商品・価格・店舗・日付) | ✅ | ✅ | | 最安値の検索 | ✅(SQL) | ✅(Graph Query) | | 価格の履歴管理 | ✅ | ✅(関係性を活用) | | 商品と店舗の関係分析 | ❌ | ✅(ネットワーク解析) | | セール・特売情報との連携 | ❌ | ✅(リレーション活用) |
SQLite は「履歴管理」「最安値検索」に適している
Neo4j は「店舗と商品の関係分析」「価格変動の視覚化」に向いている
SQLite のデータを Neo4j に同期させることで、購入履歴と分析機能を両方活用できる
現在のディレクトリは
ls
の結果
csv_files receipts.db import_receipts_with_dedup_and_log.py skipped.csv medication_summary.py
となっている
次に SqliteDBに
purchases テーブルがあることを確認
sqlite3 receipts.db
を実行し
.tables
を実行
import_log purchases
とテーブルが表示されればOK
さらに構造を確認するには
.schema purchases
とすれば
CREATE TABLE purchases (
id INTEGER PRIMARY KEY AUTOINCREMENT,
store TEXT,
date TEXT,
item TEXT,
unit_price INTEGER,
total_price INTEGER,
quantity INTEGER,
self_med_amount INTEGER,
UNIQUE(date, store, item)
);
というように表示される
次に
SQLite のデータを Neo4j に同期させる
現在SQLite DBで
Enter ".help" for usage hints.
sqlite> .tables
import_log purchases
sqlite> .schema purchases
CREATE TABLE purchases (
id INTEGER PRIMARY KEY AUTOINCREMENT,
store TEXT,
date TEXT,
item TEXT,
unit_price INTEGER,
total_price INTEGER,
quantity INTEGER,
self_med_amount INTEGER,
UNIQUE(date, store, item)
);
という構造になっている
これは
購入店舗名,購入年月日,商品名,単品税抜価格,価格,個数,セルフメディケーション対象金額 杏林堂 袋井旭町店,2025/06/18,サンテビオ 15mL,968,871,1,871 ピアゴ 袋井店,2025/04/18,タイレノールA 30錠,1790,1772,1,1772 COOP ユーコープ 袋井町店,2025/06/19,COゼリーエネルギー,118,354,3,0 COOP ユーコープ 袋井町店,2025/06/19,鮭・くず桜,238,190,1,0 COOP ユーコープ 袋井町店,2025/06/19,天ぷら用えび,398,238,1,0 COOP ユーコープ 袋井町店,2025/06/19,たい,398,398,1,0 COOP ユーコープ 袋井町店,2025/06/19,塩銀鮭切身,398,398,1,0 COOP ユーコープ 袋井町店,2025/06/19,真あじ開き,398,796,2,0 ドラッグストア クリエイト 袋井山名店,2025/06/18,日興フーズ 王様のチーズ,298,298,1,0 ドラッグストア クリエイト 袋井山名店,2025/06/18,ロイヤルブレッド山型(5),139,139,1,0 ドラッグストア クリエイト 袋井山名店,2025/06/18,家族の潤い白桃ミックス,108,216,2,0 ドラッグストア クリエイト 袋井山名店,2025/06/18,鶏卵卵パック MS 10個,228,228,1,0
という購入履歴をDBにしたもの
これを
SQLite と Neo4j を組み合わせ
それぞれの役割を明確にし、データの流れを整理すれば、最適な購買管理システムを構築する
なお元になるcsvファイルは毎日の買い物なので毎日更新される
目的が「毎日追加されるCSVの購入データを元に、SQLiteとNeo4jを連携して購買管理を最適化すること」
✅ システム構成の概要
項目 内容
SQLiteの役割 生データの保存。CSVから読み込んだ構造化データを記録。
→ 変更・削除・追加が簡単なローカル台帳的役割。
Neo4jの役割 関係性を活用した分析(例:購入頻度・店舗との関係・カテゴリ分析)
→ 推薦、店舗の傾向把握、消費パターン予測
CSVの流れ 日次で新しいCSVが追加 → SQLiteに取り込み → Neo4jに同期(新規 or 更新)
SQLiteスキーマ(そのままでOK)
UNIQUE(date, store, item) により同じ日・店舗・商品は1件のみ保存される(重複防止)。
CREATE TABLE purchases (
id INTEGER PRIMARY KEY AUTOINCREMENT,
store TEXT,
date TEXT,
item TEXT,
unit_price INTEGER,
total_price INTEGER,
quantity INTEGER,
self_med_amount INTEGER,
UNIQUE(date, store, item)
);
Neo4jの構造例
以下のようにグラフ構造で格納
(:Store {name: "杏林堂 袋井旭町店"})
-[:PURCHASED_ON {date: "2025-06-18", unit_price: 968, ...}]->
(:Item {name: "サンテビオ 15mL"})
Store ノード:店舗
Item ノード:商品
:PURCHASED_ON リレーション:購入関係と属性(日付・価格・数量など)
🔁 データフロー(毎日更新の流れ)
1. CSV読み込み → SQLiteにINSERT
2. SQLiteから新規・更新データ抽出
3. Neo4jに同期(MERGEでノードとリレーションを作成)
次に実践
まずは docker を起動する
Mac の場合
docker compose up -d
を実行しても
Cannot connect to the Docker daemon at unix:///Users/snowpool/.docker/run/docker.sock. Is the docker daemon running?
となるため
あらかじめ docker desktop を立ち上げておく必要がある
docker compose up -d
を再度実行
[+] Running 1/1 ✔ Container ne4j_pg-neo4j-1 Started
次に
vim link_sql_in_ne04jdb.py
で
from neo4j import GraphDatabase
import sqlite3
# SQLiteに接続
conn = sqlite3.connect('receipts.db')
cursor = conn.cursor()
# Neo4jに接続(適宜、ユーザー名・パスワードを置き換えてください)
neo4j_driver = GraphDatabase.driver("bolt://localhost:7687", auth=("neo4j", "your_password"))
# データ取得
cursor.execute("SELECT store, date, item, unit_price, total_price, quantity, self_med_amount FROM purchases")
rows = cursor.fetchall()
def insert_to_neo4j(tx, store, date, item, unit_price, total_price, quantity, self_med_amount):
tx.run("""
MERGE (s:Store {name: $store})
MERGE (i:Item {name: $item})
MERGE (s)-[r:PURCHASED_ON {date: $date}]->(i)
SET r.unit_price = $unit_price,
r.total_price = $total_price,
r.quantity = $quantity,
r.self_med_amount = $self_med_amount
""", store=store, date=date, item=item,
unit_price=unit_price, total_price=total_price,
quantity=quantity, self_med_amount=self_med_amount)
# Neo4jに書き込み
with neo4j_driver.session() as session:
for row in rows:
session.write_transaction(insert_to_neo4j, *row)
# 接続終了
conn.close()
neo4j_driver.close()
これを実行すると
Traceback (most recent call last):
File "/Users/snowpool/aw10s/purcharge_history/link_sql_in_ne04jdb.py", line 1, in <module>
from neo4j import GraphDatabase
ModuleNotFoundError: No module named 'neo4j'
となる
Pythonバージョンをアップしたのが原因
pip install neo4j
でインストール
Collecting neo4j Downloading neo4j-5.28.1-py3-none-any.whl.metadata (5.9 kB) Requirement already satisfied: pytz in /Users/snowpool/.pyenv/versions/3.11.0/lib/python3.11/site-packages (from neo4j) (2024.2) Downloading neo4j-5.28.1-py3-none-any.whl (312 kB) Installing collected packages: neo4j Successfully installed neo4j-5.28.1 [notice] A new release of pip is available: 24.3.1 -> 25.1.1 [notice] To update, run: pip install --upgrade pip
今度は
/Users/snowpool/aw10s/purcharge_history/link_sql_in_ne04jdb.py:31: DeprecationWarning: write_transaction has been renamed to execute_write session.write_transaction(insert_to_neo4j, *row)
となる
これは
write_transaction() は 非推奨(Deprecated) になり、代わりに execute_write() を使うように変更されているため
このためコード変更
# 旧(警告が出る) session.write_transaction(insert_to_neo4j, *row) # 新(推奨される書き方) session.execute_write(insert_to_neo4j, *row)
このため
with neo4j_driver.session() as session:
for row in rows:
session.execute_write(insert_to_neo4j, *row)
と変更
| 状態 | メソッド名 | 備考 | | ------ | --------------------- | ------------- | | ✅ 推奨 | `execute_write()` | Neo4j 5.x以降向け | | ⚠️ 非推奨 | `write_transaction()` | 古いコードとの互換性用 |
これで再度
python link_sql_in_ne04jdb.py
を実行すると
graphDBが作成される