|
import json
|
|
import re
|
|
from neo4j import GraphDatabase
|
|
|
|
|
|
def sanitize_string(input_str, max_length=255):
|
|
"""
|
|
Process the input string to ensure it meets the database requirements.
|
|
"""
|
|
|
|
input_str = re.sub(r'[^a-zA-Z0-9_]', '_', input_str)
|
|
|
|
|
|
if input_str[0].isdigit():
|
|
input_str = 'num' + input_str
|
|
|
|
|
|
if len(input_str) > max_length:
|
|
input_str = input_str[:max_length]
|
|
|
|
return input_str
|
|
|
|
|
|
def generate_cypher_statements(data):
|
|
"""
|
|
Generates Cypher query statements based on the provided JSON data.
|
|
"""
|
|
cypher_statements = []
|
|
parsed_data = json.loads(data)
|
|
|
|
def create_statement(triple):
|
|
head = triple.get("head")
|
|
head_type = triple.get("head_type")
|
|
relation = triple.get("relation")
|
|
relation_type = triple.get("relation_type")
|
|
tail = triple.get("tail")
|
|
tail_type = triple.get("tail_type")
|
|
|
|
|
|
head_type_safe = sanitize_string(head_type) if head_type else None
|
|
|
|
relation_type_safe = sanitize_string(relation_type) if relation_type else None
|
|
|
|
tail_type_safe = sanitize_string(tail_type) if tail_type else None
|
|
|
|
statement = ""
|
|
if head:
|
|
if head_type_safe:
|
|
statement += f'MERGE (a:{head_type_safe} {{name: "{head}"}}) '
|
|
else:
|
|
statement += f'MERGE (a:UNTYPED {{name: "{head}"}}) '
|
|
if tail:
|
|
if tail_type_safe:
|
|
statement += f'MERGE (b:{tail_type_safe} {{name: "{tail}"}}) '
|
|
else:
|
|
statement += f'MERGE (b:UNTYPED {{name: "{tail}"}}) '
|
|
if relation:
|
|
if head and tail:
|
|
if relation_type_safe:
|
|
statement += f'MERGE (a)-[:{relation_type_safe} {{name: "{relation}"}}]->(b);'
|
|
else:
|
|
statement += f'MERGE (a)-[:UNTYPED {{name: "{relation}"}}]->(b);'
|
|
else:
|
|
statement += ';' if statement != "" else ''
|
|
else:
|
|
if relation_type_safe:
|
|
statement += f'MERGE (a)-[:{relation_type_safe} {{name: "{relation_type_safe}"}}]->(b);'
|
|
else:
|
|
statement += ';' if statement != "" else ''
|
|
return statement
|
|
|
|
if "triple_list" in parsed_data:
|
|
for triple in parsed_data["triple_list"]:
|
|
cypher_statements.append(create_statement(triple))
|
|
else:
|
|
cypher_statements.append(create_statement(parsed_data))
|
|
|
|
return cypher_statements
|
|
|
|
|
|
def execute_cypher_statements(uri, user, password, cypher_statements):
|
|
"""
|
|
Executes the generated Cypher query statements.
|
|
"""
|
|
driver = GraphDatabase.driver(uri, auth=(user, password))
|
|
|
|
with driver.session() as session:
|
|
for statement in cypher_statements:
|
|
session.run(statement)
|
|
print(f"Executed: {statement}")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
driver.close()
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
test_data = '''
|
|
{
|
|
"triple_list": [
|
|
{
|
|
"head": "J.K. Rowling",
|
|
"head_type": "Person",
|
|
"relation": "wrote",
|
|
"relation_type": "Actions",
|
|
"tail": "Fantastic Beasts and Where to Find Them",
|
|
"tail_type": "Book"
|
|
},
|
|
{
|
|
"head": "Fantastic Beasts and Where to Find Them",
|
|
"head_type": "Book",
|
|
"relation": "extra section of",
|
|
"relation_type": "Affiliation",
|
|
"tail": "Harry Potter Series",
|
|
"tail_type": "Book"
|
|
},
|
|
{
|
|
"head": "J.K. Rowling",
|
|
"head_type": "Person",
|
|
"relation": "wrote",
|
|
"relation_type": "Actions",
|
|
"tail": "Harry Potter Series",
|
|
"tail_type": "Book"
|
|
},
|
|
{
|
|
"head": "Harry Potter Series",
|
|
"head_type": "Book",
|
|
"relation": "create",
|
|
"relation_type": "Actions",
|
|
"tail": "Dumbledore",
|
|
"tail_type": "Person"
|
|
},
|
|
{
|
|
"head": "Fantastic Beasts and Where to Find Them",
|
|
"head_type": "Book",
|
|
"relation": "mention",
|
|
"relation_type": "Actions",
|
|
"tail": "Dumbledore",
|
|
"tail_type": "Person"
|
|
},
|
|
{
|
|
"head": "Voldemort",
|
|
"head_type": "Person",
|
|
"relation": "afrid",
|
|
"relation_type": "Emotion",
|
|
"tail": "Dumbledore",
|
|
"tail_type": "Person"
|
|
},
|
|
{
|
|
"head": "Voldemort",
|
|
"head_type": "Person",
|
|
"relation": "robs",
|
|
"relation_type": "Actions",
|
|
"tail": "the Elder Wand",
|
|
"tail_type": "Weapon"
|
|
},
|
|
{
|
|
"head": "the Elder Wand",
|
|
"head_type": "Weapon",
|
|
"relation": "belong to",
|
|
"relation_type": "Affiliation",
|
|
"tail": "Dumbledore",
|
|
"tail_type": "Person"
|
|
}
|
|
]
|
|
}
|
|
'''
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
cypher_statements = generate_cypher_statements(test_data)
|
|
|
|
|
|
for statement in cypher_statements:
|
|
print(statement)
|
|
print("\n")
|
|
|
|
|
|
execute_cypher_statements(
|
|
uri="neo4j://localhost:7687",
|
|
user="your_username",
|
|
password="your_password",
|
|
cypher_statements=cypher_statements,
|
|
)
|
|
|