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.

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

1 Like

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. https://neo4j.com/docs/api/python-driver/4.4/api.html#neo4j.Result.consume

1 Like

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