2

I am trying to import a JSON file obtained thru an API request to StackOverflow to NEO4J. I have been following this tutorial. However, I get errors like the following while trying to execute the query:

  File "/Users/ahmedov/anaconda/lib/python2.7/site-packages/py2neo/cypher/core.py", line 306, in commit
    return self.post(self.__commit or self.__begin_commit)

  File "/Users/ahmedov/anaconda/lib/python2.7/site-packages/py2neo/cypher/core.py", line 261, in post
    raise self.error_class.hydrate(error)

  File "/Users/ahmedov/anaconda/lib/python2.7/site-packages/py2neo/cypher/error/core.py", line 54, in hydrate
    error_cls = getattr(error_module, title)

AttributeError: 'module' object has no attribute 'SyntaxError'

I am using the following code:

import os
import requests
from py2neo import neo4j
from py2neo import Graph

from py2neo import Path, authenticate
# set up authentication parameters
authenticate("localhost:7474", "neo4j", "neo4j")

# connect to authenticated graph database
#graph = Graph("http://localhost:7474/db/data/")

# Connect to graph and add constraints.
neo4jUrl = os.environ.get('NEO4J_URL',"http://localhost:7474/db/data/")
graph = neo4j.Graph(neo4jUrl)

# Connect to graph and add constraints.
#neo4jUrl = os.environ.get('NEO4J_URL',"http://localhost:7474/db/data/")
#graph = neo4j.GraphDatabaseService(neo4jUrl)

# Add uniqueness constraints.
graph.cypher.execute("CREATE CONSTRAINT ON (q:Question) ASSERT q.id IS UNIQUE;")
# Build URL.
apiUrl ="https://api.stackexchange.com/2.2/questions?pagesize=100&order=desc&sort=creation&tagged=neo4j&site=stackoverflow&filter=!5-i6Zw8Y)4W7vpy91PMYsKM-k9yzEsSC1_Uxlf"
# Send GET request.
json = requests.get(apiUrl, headers = {"accept":"application/json"}).json()

# Build query.
query = """
UNWIND data.items as q
MERGE (question:Question {id:q.question_id}) ON CREATE
  SET question.title = q.title, question.share_link = q.share_link, question.favorite_count = q.favorite_count

MERGE (owner:User {id:q.owner.user_id}) ON CREATE SET owner.display_name = q.owner.display_name
MERGE (owner)-[:ASKED]->(question)

FOREACH (tagName IN q.tags | MERGE (tag:Tag {name:tagName}) MERGE (question)-[:TAGGED]->(tag))
FOREACH (a IN q.answers |
   MERGE (question)<-[:ANSWERS]-(answer:Answer {id:a.answer_id})
   MERGE (answerer:User {id:a.owner.user_id}) ON CREATE SET answerer.display_name = a.owner.display_name
   MERGE (answer)<-[:PROVIDED]-(answerer)
)

"""
statement = "MERGE (n:Person {name:{N}}) RETURN n"
results = graph.cypher.run(query,json=json)

tx = graph.cypher.begin()

def add_names(*names):
    for name in names:
        tx.append(statement, {"N": name})
    tx.process()

add_names("Homer", "Marge", "Bart", "Lisa", "Maggie")
add_names("Peter", "Lois", "Chris", "Meg", "Stewie")
tx.append(query,)
tx.commit()
# Send Cypher query.

The problem originates from the following line:

    results = graph.cypher.run(query,json=json)

I had to change the above line to adjust it to the newer py2neo api. The original line looked like this:

neo4j.CypherQuery(graph, query).run(json=json)

So basically, I need to find a way to tell neo4j that I need to process the JSON file using the given query. I tried to read the documentary and searching the web with no luck. Any help would be appreciated.

Ahmadov
  • 1,567
  • 5
  • 31
  • 48

2 Answers2

6

A couple of things to make your script work :

from py2neo import neo4j is not a valid dependency anymore

In your query, you pass a json map as parameter but you don't use the parameters syntax in the query, I added WITH {json} as data in the beginning of the query.

Added secure=False for the connection

The last tx.append(query,) is not needed.

Working script :

import os
import requests
#from py2neo import neo4j
from py2neo import Graph
from py2neo import Path, authenticate
# set up authentication parameters
authenticate("localhost:7474", "neo4j", "neo4j")

# connect to authenticated graph database
#graph = Graph("http://localhost:7474/db/data/")

# Connect to graph and add constraints.
neo4jUrl = os.environ.get('NEO4J_URL',"http://localhost:7474/db/data/")
graph = Graph(neo4jUrl,secure=False)

# Connect to graph and add constraints.
#neo4jUrl = os.environ.get('NEO4J_URL',"http://localhost:7474/db/data/")
#graph = neo4j.GraphDatabaseService(neo4jUrl)

# Add uniqueness constraints.
graph.run("CREATE CONSTRAINT ON (q:Question) ASSERT q.id IS UNIQUE;")
# Build URL.
apiUrl ="https://api.stackexchange.com/2.2/questions?pagesize=100&order=desc&sort=creation&tagged=neo4j&site=stackoverflow&filter=!5-i6Zw8Y)4W7vpy91PMYsKM-k9yzEsSC1_Uxlf"
# Send GET request.
json = requests.get(apiUrl, headers = {"accept":"application/json"}).json()

#print(json);

# Build query.
query = """
WITH {json} as data
UNWIND data.items as q
MERGE (question:Question {id:q.question_id}) ON CREATE
  SET question.title = q.title, question.share_link = q.share_link, question.favorite_count = q.favorite_count

MERGE (owner:User {id:q.owner.user_id}) ON CREATE SET owner.display_name = q.owner.display_name
MERGE (owner)-[:ASKED]->(question)

FOREACH (tagName IN q.tags | MERGE (tag:Tag {name:tagName}) MERGE (question)-[:TAGGED]->(tag))
FOREACH (a IN q.answers |
   MERGE (question)<-[:ANSWERS]-(answer:Answer {id:a.answer_id})
   MERGE (answerer:User {id:a.owner.user_id}) ON CREATE SET answerer.display_name = a.owner.display_name
   MERGE (answer)<-[:PROVIDED]-(answerer)
)

"""
statement = "MERGE (n:Person {name:{N}}) RETURN n"
results = graph.run(query,json=json)

tx = graph.begin()

def add_names(*names):
    for name in names:
        tx.append(statement, {"N": name})
    tx.process()

add_names("Homer", "Marge", "Bart", "Lisa", "Maggie")
add_names("Peter", "Lois", "Chris", "Meg", "Stewie")
#tx.append(query,)
tx.commit()

Result :

enter image description here

Christophe Willemsen
  • 19,399
  • 2
  • 29
  • 36
  • I still get a few errors: File "/Users/ahmedov/neo4j.py", line 14, in graph = Graph(neo4jUrl,secure=False) TypeError: __new__() got an unexpected keyword argument 'secure' then, if I remove secure = false, I get: File "/Users/ahmedov/neo4j.py", line 21, in graph.run("CREATE CONSTRAINT ON (q:Question) ASSERT q.id IS UNIQUE;") AttributeError: 'Graph' object has no attribute 'run' – Ahmadov Jul 14 '16 at 10:34
  • 1
    it seems you have a mismatch of py2neo versions, can you run `pip install py2neo --upgrade` – Christophe Willemsen Jul 14 '16 at 10:49
  • Thanks! finally got it working. Now it is time to solve a similar problem for the java driver :) – Ahmadov Jul 14 '16 at 11:17
0

Using a recent version of py2neo, the syntax changes a little bit. Rather than use {json}, is necessary to use $json as explained below:

from py2neo import Graph

graph = Graph(NEO4J_URI, user=NEO4J_USER, password=NEO4j_PASSWORD)

json = ['22644198319', '15383242341']

result = graph.run(
    """WITH $json as data
    UNWIND data as id
    MATCH (c:Person {id: id}) RETURN c.name""", 
    json=json
)
data_frame_result = result.to_data_frame()
print(data_frame_result)

Making these changes in the @christophe-willemsen's example, the code can run in the newest versions.

Aipi
  • 2,076
  • 4
  • 18
  • 27