python neo4j py2neo

python - Falló la operación de WriteBatch con py2neo



neo4j (2)

Su problema parece no estar en batch.set_properties() sino en el resultado de batch.get_or_create_in_index() . Si agrega el nodo con batch.create() , funciona:

db = neo4j.GraphDatabaseService() batch = neo4j.WriteBatch(db) # create a node instead of getting it from index test_node = batch.create({''key'': ''value''}) # set new properties on the node batch.set_properties(test_node, {''key'': ''foo''}) batch.submit()

Si echa un vistazo a las propiedades del objeto BatchRequest devuelto por batch.create() y batch.get_or_create_in_index() existe una diferencia en el URI porque los métodos utilizan diferentes partes de la API de REST neo4j:

test_node = batch.create({''key'': ''value''}) print test_node.uri # node print test_node.body # {''key'': ''value''} print test_node.method # POST index_node = batch.get_or_create_in_index(neo4j.Node, "Users", "user_id", 12345, {}) print index_node.uri # index/node/Users?uniqueness=get_or_create print index_node.body # {u''value'': 12345, u''key'': ''user_id'', u''properties'': {}} print index_node.method # POST batch.submit()

Entonces, ¿supongo que batch.set_properties() alguna manera no puede manejar el URI del nodo indexado? Es decir, ¿realmente no obtiene el URI correcto para el nodo?

No resuelve el problema, pero podría ser un puntero para otra persona;)?

Estoy tratando de encontrar una solución al siguiente problema. Lo he visto cuasi-descrito en esta pregunta SO , pero realmente no ha sido respondido.

El siguiente código falla, comenzando con un nuevo gráfico:

from py2neo import neo4j def add_test_nodes(): # Add a test node manually alice = g.get_or_create_indexed_node("Users", "user_id", 12345, {"user_id":12345}) def do_batch(graph): # Begin batch write transaction batch = neo4j.WriteBatch(graph) # get some updated node properties to add new_node_data = {"user_id":12345, "name": "Alice"} # batch requests a = batch.get_or_create_in_index(neo4j.Node, "Users", "user_id", 12345, {}) batch.set_properties(a, new_node_data) #<-- I''m the problem # execute batch requests and clear batch.run() batch.clear() if __name__ == ''__main__'': # Initialize Graph DB service and create a Users node index g = neo4j.GraphDatabaseService() users_idx = g.get_or_create_index(neo4j.Node, "Users") # run the test functions add_test_nodes() alice = g.get_or_create_indexed_node("Users", "user_id", 12345) print alice do_batch(g) # get alice back and assert additional properties were added alice = g.get_or_create_indexed_node("Users", "user_id", 12345) assert "name" in alice

En resumen, deseo, en una transacción por lotes, actualizar las propiedades de nodo indexadas existentes. La falla se produce en la línea batch.set_properties , y se debe a que el objeto BatchRequest devuelto por la línea anterior no se interpreta como un nodo válido. Aunque no es del todo idéntico, parece que estoy intentando algo así como la respuesta publicada aquí

Algunos detalles

>>> import py2neo >>> py2neo.__version__ ''1.6.0'' >>> g = py2neo.neo4j.GraphDatabaseService() >>> g.neo4j_version (2, 0, 0, u''M06'')

Actualizar

Si dividí el problema en lotes separados, puede ejecutarse sin error:

def do_batch(graph): # Begin batch write transaction batch = neo4j.WriteBatch(graph) # get some updated node properties to add new_node_data = {"user_id":12345, "name": "Alice"} # batch request 1 batch.get_or_create_in_index(neo4j.Node, "Users", "user_id", 12345, {}) # execute batch request and clear alice = batch.submit() batch.clear() # batch request 2 batch.set_properties(a, new_node_data) # execute batch request and clear batch.run() batch.clear()

Esto funciona para muchos nodos también. Aunque no me gusta la idea de dividir el lote, esta podría ser la única forma en este momento. Alguien tiene algunos comentarios sobre esto?


Después de leer todas las características nuevas de Neo4j 2.0.0-M06, parece que se está reemplazando el flujo de trabajo anterior de los índices de nodo y relación. Actualmente existe una cierta divergencia por parte de neo en la forma en que se realiza la indexación. A saber, etiquetas e índices de esquema .

Etiquetas

Las etiquetas se pueden unir arbitrariamente a los nodos y pueden servir como referencia para un índice.

Índices

Los índices se pueden crear en Cypher haciendo referencia a las etiquetas (aquí, User ) y la clave de propiedad del nodo, ( screen_name ):

CREATE INDEX ON :User(screen_name)

Cypher MERGE

Además, los métodos get_or_create indexados ahora son posibles a través de la nueva función CREE MERGE , que incorpora Labels y sus índices de manera muy sucinta:

MERGE (me:User{screen_name:"SunPowered"}) RETURN me

Lote

Las consultas de este tipo se pueden py2neo en py2neo añadiendo una instancia de CypherQuery al objeto por lotes:

from py2neo import neo4j graph_db = neo4j.GraphDatabaseService() cypher_merge_user = neo4j.CypherQuery(graph_db, "MERGE (user:User {screen_name:{name}}) RETURN user") def get_or_create_user(screen_name): """Return the user if exists, create one if not""" return cypher_merge_user.execute_one(name=screen_name) def get_or_create_users(screen_names): """Apply the get or create user cypher query to many usernames in a batch transaction""" batch = neo4j.WriteBatch(graph_db) for screen_name in screen_names: batch.append_cypher(cypher_merge_user, params=dict(name=screen_name)) return batch.submit() root = get_or_create_user("Root") users = get_or_create_users(["alice", "bob", "charlie"])

Limitación

Sin embargo, existe una limitación en que los resultados de una consulta de cifrado en una transacción por lotes no se pueden referenciar más adelante en la misma transacción. La pregunta original se refería a la actualización de una colección de propiedades de usuario indexadas en una transacción por lotes. Esto no es posible, por lo que puedo reunir. Por ejemplo, el siguiente fragmento arroja un error:

batch = neo4j.WriteBatch(graph_db) b1 = batch.append_cypher(cypher_merge_user, params=dict(name="Alice")) batch.set_properties(b1, dict(last_name="Smith")}) resp = batch.submit()

Por lo tanto, parece que aunque hay un poco menos de sobrecarga en la implementación del get_or_create sobre un nodo etiquetado que usa py2neo porque los índices heredados ya no son necesarios, la pregunta original aún necesita 2 transacciones por lotes separadas para completarse.