RedisGraph / redisgraph-py

RedisGraph python client
https://redisgraph.io
BSD 3-Clause "New" or "Revised" License
189 stars 49 forks source link

_AR_EXP_UpdateEntityIdx error when adding nodes to graph #73

Open DrPyser opened 4 years ago

DrPyser commented 4 years ago

Hi!

ResponseError                           Traceback (most recent call last)
~/repositories/redisgraph_test/main.py in <module>
     36                 graph.add_node(redisgraph.Node(label="account", properties=a))
     37
---> 38         qr = graph.commit()
     39         print(str(qr))

~/.local/share/virtualenvs/redisgraph_test-RxknWNSK/lib/python3.7/site-packages/redisgraph/graph.py in commit(self)
     94             query = query[:-1]
     95
---> 96         return self.query(query)
     97
     98     def flush(self):

~/.local/share/virtualenvs/redisgraph_test-RxknWNSK/lib/python3.7/site-packages/redisgraph/graph.py in query(self, q, params)
    129
    130         response = self.redis_con.execute_command("GRAPH.QUERY", self.name, q, "--compact")
--> 131         return QueryResult(self, response)
    132
    133     def _execution_plan_to_string(self, plan):

~/.local/share/virtualenvs/redisgraph_test-RxknWNSK/lib/python3.7/site-packages/redisgraph/query_result.py in __init__(self, graph, response)
     43         # If we encountered a run-time error, the last response element will be an exception.
     44         if isinstance(response[-1], ResponseError):
---> 45             raise response[-1]
     46
     47         if len(response) is 1:

ResponseError: _AR_EXP_UpdateEntityIdx: Unable to locate a value with alias None within the record

I'm getting this error while trying to create a bunch of nodes, pretty basic stuff. The error was a bit cryptic for me, and I didn't find anything googling it, documentation-wise or similar question answered. Well, except the redisgraph code:

https://github.com/RedisGraph/RedisGraph/blob/0cf50df86d5846c1eba39b2c0fcf1f500c25abf2/src/arithmetic/arithmetic_expression.c#L327-L348

My guess is that this is a datatype mapping issue(None values are not automatically translated to cypher NULL). If so, what is the right way to encode a null value in a record?

I think it would be helpful to users to have some error interpretation between the raw redisgraph protocol messages and the client library user.

Thanks!

swilly22 commented 4 years ago

Hi @DrPyser, I agree, we should improve our error reporting,

Would you mind letting us know what does a stands for in:

 graph.add_node(redisgraph.Node(label="account", properties=a))

I would like to see the actual query which was issued, one way of finding out is to have redis-cli running with the MONITOR command and then run your python script. you should see all of the commands received by your redis-server in the monitor.

DrPyser commented 4 years ago
    for a in accounts:
        print("a=",a)
        if a["mcc"] == "True":
            a.update(mcc=True)
        if a["mcc"] == "False":
            a.update(mcc=False)
        if a["parent_id"] == "<null>":
            a.update(parent_id=None)
        graph.add_node(redisgraph.Node(label="account", properties=a))

Basically, I'm loading data from a csv and creating "account" entities. Some attributes will be null.

DrPyser commented 4 years ago

An extract from the actual cypher query:

 "GRAPH.QUERY" "accounts" "CREATE (hpebuobbzn:account{account_id:\"310-095-8250\",name:\"Fondation Mira\",parent_id:None,mcc:False})

I guess it should be converting the None to a null, right?

jeffreylovitz commented 4 years ago

Hi @DrPyser,

null is a somewhat tricky beast in Cypher, and RedisGraph is not totally consistent in this respect.

The main problem is that null is not actually allowed by Cypher to be the value of a property, though both the bulk loader and the CREATE clause will allow null values to be set (which is an error on our part).

When you perform property accesses on non-existent properties, null is returned, which sets up the more orthodox approach here. By not setting parent_id at all where it's currently null, you can write queries such as:

MATCH (a:account) WHERE a.parent_id IS NULL RETURN a
MATCH (a:account) WHERE a.parent_id IS NOT NULL RETURN a
MATCH (a:account) WHERE exists(a.parent_id) RETURN a
DrPyser commented 4 years ago

Okay, I got it. Thanks!