|
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, |
|
) |
|
|