cancel
Showing results for 
Search instead for 
Did you mean: 

Head's Up! These forums are read-only. All users and content have migrated. Please join us at community.neo4j.com.

Python neo4j driver get result from session.run()

Hi,


I am using python to populate and drop data on neo4j with neo4j-python.
While dropping the nodes, I'm running a query like:

call apoc.periodic.iterate("MATCH (n {data_source:'APAC'})
return n", "DETACH DELETE n", {batchSize:10000})
yield batches, total return total AS count

Which is being called via this Neo4jDriver class:

class Neo4JDriver:

    def __init__(self, url, user, password, encrypted=False):
        self._driver = GraphDatabase.driver(url, auth=(user, password), encrypted=encrypted)

    def close(self):
        self._driver.close()

    def exec_cypher_query(self, query):
        logger.info("Firing query :: {}".format(query))
        with self._driver.session() as session:
            return session.run(query)

The query runs fine and does it job, but when I try to retrieve the 'count' from the Result object as in the following query:

result = exec_cypher_query(query)

But I cannot find the value of count in the result variable. I have debugged the code, and trying to follow many suggestions available in different forums, but for no success.


Earlier, I was using query:

MATCH (n {label} {props})
DETACH DELETE n 
RETURN COUNT(n) as count

After which I used to get the number of deleted nodes using:

if 'stats' in result._metadata:
                count = result._metadata['stats']['nodes-deleted']

But this does not seem to working using the new query for batch wise delete.
Please suggest some way to get the count of nodes getting deleted. I'm really stuck,

Thanks. Cheers.

1 ACCEPTED SOLUTION

Result set objects do not outlive the session @mihaque313

The error is here:

    def exec_cypher_query(self, query):
        logger.info("Firing query :: {}".format(query))
        with self._driver.session() as session:
            return session.run(query)

The way this code works is that the "with" block creates a session, and then closes the session when you're outside of the block. So the caller of exec_cypher_query can't consume the results because they're already gone with the session.

The solution is to convert the results from the result set to some kind of object that can be used by the caller.

Here's an example:

    def exec_cypher_query(self, query):
        logger.info("Firing query :: {}".format(query))
        with self._driver.session() as session:
            r = session.run(query)
            return [ dict(i) for i in r]

Notice this does not return a Neo4j result set it returns an array of results taken out of the result set, converting each one into a dictionary.

It's good practice to convert Neo4j results to some kind of native types before returning them, because this way the logic of exec_cypher_query can handle how you want to unpack those values and what schema to return and so on. If you were to return raw Neo4j results, then every caller of that function would need to know how to use the Neo4j results API

View solution in original post

3 REPLIES 3

Result set objects do not outlive the session @mihaque313

The error is here:

    def exec_cypher_query(self, query):
        logger.info("Firing query :: {}".format(query))
        with self._driver.session() as session:
            return session.run(query)

The way this code works is that the "with" block creates a session, and then closes the session when you're outside of the block. So the caller of exec_cypher_query can't consume the results because they're already gone with the session.

The solution is to convert the results from the result set to some kind of object that can be used by the caller.

Here's an example:

    def exec_cypher_query(self, query):
        logger.info("Firing query :: {}".format(query))
        with self._driver.session() as session:
            r = session.run(query)
            return [ dict(i) for i in r]

Notice this does not return a Neo4j result set it returns an array of results taken out of the result set, converting each one into a dictionary.

It's good practice to convert Neo4j results to some kind of native types before returning them, because this way the logic of exec_cypher_query can handle how you want to unpack those values and what schema to return and so on. If you were to return raw Neo4j results, then every caller of that function would need to know how to use the Neo4j results API

Thanks! David. Your suggestion worked!.
Didn't realize I was querying inside 'with' block.

An additional remark: it's not advised to rely on internal attributes starting with _ (result._metadata in this case). It might be renamed, removed or re-purposed even in patch releases. Moreover, it's undocumented and might involve more complex behavior than it appears to. If you want to access the metadata of a query, you can use Result.consume() which yields a ResultSummaryobject that gives you access to what you need. API Documentation — Neo4j Python Driver 4.4