Defining label/s during create(node()) in batches - py2neo

As I understand from the documentation of py2neo, the only way to add a label to a node is to use the add_labels() function, after the node is created. Is there any way to define label/s in the create(node()) function?

The only option right now is to use Cypher to create the node instead of the 'create' method. This is because the underlying REST resource does not support creation of nodes with labels. The next version of py2neo (currently in beta) will make the process slightly simpler, allowing labels to be used through the 'create' method by wrapping Cypher directly instead.

You can now add labels to nodes when you create them.
From the docs:
from py2neo import Node
alice = Node("Person", name="Alice")
banana = Node("Fruit", "Food", colour="yellow", tasty=True)

Related

is is Possible oin CYPHER to Set (Copy) the Labels of Another Node?

I want to set the labels of a newly-merged node to the labels of an existing node. I'm pretty sure that the following worked :-
SET sub_practice:labels(pract_parent)
but it doesn't work in 4.1 and throws an error.
Doubt it worked before. At the moment, cypher does not support assigning dynamic labels. You will have to use the APOC library to achieve this. If you want to create a node with dynamic labels you could use:
CALL apoc.create.node(['Label','Label2'], {key:value,property:value})
Or you can also just assign dynamic labels to an existing node:
CALL apoc.create.addLabels( [node,id,ids,nodes], ['Label','Label2'])

Enforcing the non-existence of relationships in Neo4j

In Neo4j, is there a way of enforcing that a node of a label X is not connected to a node of label Y?
For example, if someone tried to run a query such as:
MERGE (:X)-[:SOME_RELATIONSHIP]->(:Y)
would there be a way to guarantee that such a query would fail?
Thank you!
Neo4j's constraints don't currently support relationship existence or restriction, so you'd need to put in some extra work.
If you have APOC Procedures, you could register a trigger which could get evaluated to check if a relationship being created connects two nodes of those labels and use apoc.util.validate() to generate an error which will fail and rollback the transaction.
If you want to do this without APOC, it's a bit more work, as you'll need to create a TransactionEventHandler, and then a kernel extension to load your event handler. Here's a blog entry on this approach.

Multi-part pattern in Merge clause of Cypher

Given the following graph:
(a)<--(b)-->(c)<--(d)-->(e)<--(f)-->(a)
I believe it is (currently) impossible to create a node (g) using the merge clause such that:
(g)-->(a)
(g)-->(c)
(g)-->(e)
The reason being that it requires a comma to describe the above pattern, and the MERGE clause will not accept a comma. e.g. (a)<--(g)-->(c), (g)-->(e)
For ease of reference, see picture below. Given that graph (except node 6), I cannot create node 6 using the MERGE command.
Can someone come up with a way to do this? I believe new functionality needs to be added, but I'd like to be more reasonably sure there's not a viable workaround before heading down that path.
There is no way to do this in Cypher, or in APOC right now. That said, there is a workaround. It's a bit manual, you'll need to acquire locks on the nodes in question (we'll use APOC for that), and we'll use OPTIONAL MATCH along with WHERE ... IS NULL to determine whether or not the center node exists, then create it only when it doesn't.
For this, I'm using the following example graph to mimic yours, before the addition of node 6:
create (zero:Node{name:0})
create (one:Node{name:1})
create (two:Node{name:2})
create (three:Node{name:3})
create (four:Node{name:4})
create (five:Node{name:5})
create (zero)<-[:TYPE]-(one)-[:TYPE]->(two)
create (two)<-[:TYPE]-(three)-[:TYPE]->(four)
create (four)<-[:TYPE]-(five)-[:TYPE]->(zero)
And now, the query to merge
match (node:Node)
where node.name in [0,2,4]
with collect(node) as nodes
call apoc.lock.nodes(nodes)
with nodes[0] as first, nodes[1] as second, nodes[2] as third
optional match (first)<-[:TYPE]-(center)-[:TYPE]->(second)
where (center)-[:TYPE]->(third)
with first, second, third, center
where center is null
// above 'where' will result in no rows if center exists, preventing creation of duplicate pattern below
create (first)<-[:TYPE]-(newCenter:Node{name:6})-[:TYPE]->(second)
create (newCenter)-[:TYPE]->(third)

py2neo, create a node ? two ways?

I am confused as what is the difference between below two ways to create a node ? It seems like the result is the same;
from py2neo import Graph
graph = Graph()
graph.cypher.execute("CREATE (a:Person {name:{N}})", {"N": "Alice"}) # a
graph.create( Node("Person",name="Alice")) # b
Looking at the py2neo v3 documentation, it seems there's yet a third way to create a node.
First instantiate a Node object, as in
a = Node("Person",name="Alice")
then insert it in a subgraph (see py2neo types),
sg = Subgraph(a)
then create elements of this subgraph (Graph.create method):
graph.create(sg)
I understand that subgraph creation should however be preferred when creating numerous nodes and edges (a subgraph ...).
You're right, the result is exactly the same. Py2neo exposes two levels of API: a pure Cypher API (execute) and a simpler object-based API (Node). The latter is generally easier to get up and running with, the former is more comprehensive.

How can I specify which relationship type to use as a function of the current node at every step of a traversal with neo4j?

I'd like to traverse my graph using the neo4j traversal API, but I need to be able to specify which relationship type to use at every step, and the relationship type to use needs to be a function of the current node. Is there a way to do this?
in the current Traverser API you can't choose the exact relationship to traverse. Instead, you take the more granular approach of node.getRelationships(), chose the one you want and the end onde on it, and so on.
The algo gets a bit more verbose than using Traverser, but gives you more flexibility. For a tinkering approach, Gremlin supports the notion of functions for choosing edges to traverse, see here. This will soon be implemented using Blueprint Pipes for Java-level performance.
HTH
/peter neubauer

Resources