Set property with whitespace with py2neo

I'm trying to set a property with a value which could have with space.I'm using py2neo and I wrote this, but it doesn't work:

import re
for mention in tweet['entities']['user_mentions']:
     name = mention['name']
     screen_name = mention['screen_name']
     id = mention['id']

     graph.run(
           'MATCH (f {graph_information: [\'' + usr + '\',\'twitter\']}) '
           'WHERE EXISTS(f.account_id) AND f.account_id=\'' + id + '\' '
           'SET f.name=\'' + re.escape(name) + '\' AND f.screen_name=\'@' + screen_name + '\' '                                                     
            'RETURN null'
      )

How can I solve ? Thanks

Hi @lx2pwnd, can you share the error you're getting please? I've used py2neo but write it a bit differently than what you have (e.g. I only use one set of "" for the entire cypher statement and use the \ character at the end of lines to denote a line break).

Please let me know more about the error and I'll do my best to help out.

Dom

1 Like

Thanks for your answer. However, I get this error

SyntaxError: Invalid input ' ': expected '', ''', '"', 'b', 'f', 'n', 'r', 't', UTF16 or UTF32 (line 1, column 122 (offset: 121)) "MATCH (f {graph_information: ['admin','twitter']}) WHERE EXISTS(f.account_id) AND f.account_id='18511142' SET f.name='So\ Fain' f.screen_name='@sofain' RETURN null"

I think you might be better off using the parameters rather than hard coding the values in the query string. It also makes the query planner life bit better and query would execute faster.

First create a map (myparams) with your parameters and execute it likes this

query="""
WITH {json} as data
MATCH (f {graph_information: data.users})
WHERE EXISTS(f.account_id) AND f.account_id=data.accountId
SET f.name=data.name, f.screen_name=data.screenName
RETURN null
"""
graph.run(query, json=myparams)

This way you don't need to escape the values.

if I executed this:

    for tweet in tweets:
        if len(tweet['entities']['user_mentions']) > 0:
            mentions = json.dumps(tweet['entities']['user_mentions'])
            query = """
            WITH {json} as data
            MATCH (f)
            WHERE EXISTS(f.account_id) AND f.account_id=data.id
            SET f.name=data.name, f.screen_name=data.screen_name
            RETURN null
            """
            graph.run(query, json=mentions)

I get the error :


py2neo.database.ClientError: TypeError: Type mismatch: expected a map but was String("[{"indices": ["3", "10"], "id": "18511142", "id_str": "18511142", "name": "So Fain", "screen_name": "sofain"}]")

You need to pass the Map as parameter not a string.

Also it seems that tweet['entities']['user_mentions'] is returning an array

[{"indices": ["3", "10"], "id": "18511142", "id_str": "18511142", "name": "So Fain", "screen_name": "sofain"}]

We need it to be a simple map like

{"indices": ["3", "10"], "id": "18511142", "id_str": "18511142", "name": "So Fain", "screen_name": "sofain"}

mentions = tweet['entities']['user_mentions'][0]

Can you try that change?

1 Like

I agree with @anthapu regarding the use of parameters, but I've never passed a map as a parameter so follow the advice above. In case it might help you, here is one of the snippets I use to create a node with py2neo.

### Update existing or create new :CreditCard nodes from card_nbr column
statement = """
UNWIND $parameters as row
MERGE (c:CreditCard {number: row.card_nbr})
ON MATCH SET c += {openDt: row.open_date, closeDt: row.close_date, \
closeReasonCode: row.cls_rsn_cd}
ON CREATE SET c.openDt = row.open_date, c.closeDt = row.close_date, \
c.closeReasonCode = row.cls_rsn_cd
"""
tx = graph_engine.begin(autocommit=True)
params = []
# dataframe is indexed with numerical indexes
for index, row in fraud_df.iterrows():
    params_dict = {
        'card_nbr': row['card_nbr']
        'open_date': row['open_date']
        'close_date': row['close_date']
        'cls_rsn_cd': row['cls_rsn_cd']
    }
    params.append(params_dict)
    if index % 20000 = 0 and index > 0:
        tx.evaluate(statement, parameters = {"parameters": params})
        tx = graph_engine.begin(autocommit=True)
        params = []
tx.evaluate(statement, parameters = {"parameters": params})

The dataframe is defined earlier in my script, but that is what's providing the data obviously. Same goes for graph_engine...it's the connection to my graph. Finally, the part at the bottom with the modulo operator is how I'm periodically committing batches to the graph (in this case, every 20K records...similar to USING PERIODIC COMMIT with LOAD CSV).

1 Like

thanks a lot. Now it's works perfectly !

I already solved, but thanks for your answer