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.

Parsing responses neo4j-driver

Hi,

I'm using the V4.4.2 version of the driver and trying to execute the query below but i'm having a hard time parsing the responses.

Query:

MATCH (n:Invoice), (n)-[:HAS_INVOICE_LINE]->(line), (n)-[:HAS_BILLING_ADDRESS]->(bill_addr), (n)-[:HAS_COMPANY_ADDRESS]->(comp_addr) WHERE n.deletion_status = false RETURN n, line, bill_addr, comp_addr

The query returns the results as expected in the browser (In this case it's one but could be multiple):
3X_4_9_49fc52af117b15d32470c8a1cabd963ec419b118.png

Without downstream nodes i usually use this snippet to get it:

async def list_all() -> list:
    """
    :return
    """
    driver = Database.get_driver()
    session = driver.session()
    result = session.run(query="MATCH (n:Invoice), "
                               "(n)-[:HAS_INVOICE_LINE]->(line), "
                               "(n)-[:HAS_BILLING_ADDRESS]->(bill_addr), "
                               "(n)-[:HAS_COMPANY_ADDRESS]->(comp_addr) "
                               "WHERE n.deletion_status = false "
                               "RETURN n, line, bill_addr, comp_addr")
    values = result.data()
    session.close()
    ret = []
    for val in values:
        ret.append(val.get('n'))
    return ret

But with this query it returns it 3 times. This is due to the Invoiceline node being there 3 times i discovered using the debugger.

Is there a way to get this as a dict/json? or easily convert it to something like:

[
  {
    "companyAddress": {},
    "billingAddress": {},
    "invoiceLines": [
      {},{},{}
    ]
  }
]
1 ACCEPTED SOLUTION

Try this

MATCH (n:Invoice)
WHERE n.deletion_status = false
MATCH (n)-[:HAS_INVOICE_LINE]->(line)
WITH n, collect(line{.*}) as lines
MATCH (n)-[:HAS_BILLING_ADDRESS]->(bill_addr)
MATCH (n)-[:HAS_COMPANY_ADDRESS]->(comp_addr) 
RETURN n{.*, lines: lines, bill_addr: bill_addr{.*}, comp_addr: comp_addr{.*}}

This uses cypher map projection. It is assumed that bill_addr and comp_addr exist and there is only one instance each. You can use optional match instead they may not exist.

View solution in original post

2 REPLIES 2

Try this

MATCH (n:Invoice)
WHERE n.deletion_status = false
MATCH (n)-[:HAS_INVOICE_LINE]->(line)
WITH n, collect(line{.*}) as lines
MATCH (n)-[:HAS_BILLING_ADDRESS]->(bill_addr)
MATCH (n)-[:HAS_COMPANY_ADDRESS]->(comp_addr) 
RETURN n{.*, lines: lines, bill_addr: bill_addr{.*}, comp_addr: comp_addr{.*}}

This uses cypher map projection. It is assumed that bill_addr and comp_addr exist and there is only one instance each. You can use optional match instead they may not exist.

Thanks @glilienfield. I haven't thought about doing the heavy lifting in cypher instead of Python. It works perfectly.

Nodes 2022
Nodes
NODES 2022, Neo4j Online Education Summit

All the sessions of the conference are now available online