mgbam commited on
Commit
df3294b
·
verified ·
1 Parent(s): e995e3b

Create graphdb.py

Browse files
Files changed (1) hide show
  1. genesis/graphdb.py +81 -0
genesis/graphdb.py ADDED
@@ -0,0 +1,81 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # genesis/graphdb.py
2
+ from __future__ import annotations
3
+
4
+ import os
5
+ from typing import Dict, List
6
+
7
+ from neo4j import GraphDatabase
8
+
9
+ NEO4J_URI = os.getenv("NEO4J_URI")
10
+ NEO4J_USER = os.getenv("NEO4J_USER")
11
+ NEO4J_PASSWORD = os.getenv("NEO4J_PASSWORD")
12
+
13
+
14
+ def _require_config():
15
+ if not (NEO4J_URI and NEO4J_USER and NEO4J_PASSWORD):
16
+ raise RuntimeError(
17
+ "Neo4j not configured. Set NEO4J_URI, NEO4J_USER, NEO4J_PASSWORD in Space Secrets."
18
+ )
19
+
20
+
21
+ async def write_topic_and_papers(topic: str, citations: List[Dict[str, str]]) -> Dict[str, int]:
22
+ """
23
+ Create/merge a Topic node and Paper nodes, and connect them with MENTIONS edges.
24
+ Schema:
25
+ (t:Topic {id})-[:MENTIONS]->(p:Paper {url}) with p.title set/updated.
26
+ Returns: {"nodes": <int>, "rels": <int>}
27
+ """
28
+ _require_config()
29
+ driver = GraphDatabase.driver(NEO4J_URI, auth=(NEO4J_USER, NEO4J_PASSWORD))
30
+
31
+ nodes = 0
32
+ rels = 0
33
+ try:
34
+ with driver.session() as sess:
35
+ # Topic
36
+ sess.run(
37
+ "MERGE (t:Topic {id:$id}) SET t.title=$title",
38
+ id=(topic or "Topic")[:200],
39
+ title=(topic or "Topic")[:500],
40
+ )
41
+ nodes += 1
42
+
43
+ # Papers + edges
44
+ for c in citations or []:
45
+ title = (c.get("title") or "citation")[:500]
46
+ url = (c.get("url") or "")[:1000]
47
+ if not url and not title:
48
+ continue
49
+
50
+ sess.run(
51
+ """
52
+ MERGE (p:Paper {url:$url})
53
+ ON CREATE SET p.title=$title
54
+ ON MATCH SET p.title = coalesce(p.title, $title)
55
+ WITH p
56
+ MATCH (t:Topic {id:$topic})
57
+ MERGE (t)-[:MENTIONS]->(p)
58
+ """,
59
+ url=url,
60
+ title=title,
61
+ topic=(topic or "Topic")[:200],
62
+ )
63
+ nodes += 1
64
+ rels += 1
65
+
66
+ return {"nodes": nodes, "rels": rels}
67
+ finally:
68
+ driver.close()
69
+
70
+
71
+ # Optional helper for debugging connectivity in a notebook/Space shell
72
+ def verify_connection() -> str:
73
+ _require_config()
74
+ driver = GraphDatabase.driver(NEO4J_URI, auth=(NEO4J_USER, NEO4J_PASSWORD))
75
+ try:
76
+ with driver.session() as sess:
77
+ res = sess.run("RETURN 1 AS ok").single()
78
+ assert res and res["ok"] == 1
79
+ return "Neo4j connection OK."
80
+ finally:
81
+ driver.close()