Node and relationship matching

The py2neo.matching module provides functionality to match nodes and relationships according to certain criteria. For each entity type, a Matcher class and a Match class are provided. The Matcher can be used to perform a basic selection, returning a Match that itself can be evaluated or further refined.

The underlying query is only evaluated when the selection undergoes iteration or when a specific evaluation method is called (such as NodeMatch.first()). This means that a NodeMatch object may be reused before and after data changes for different results.

Node matching

NodeMatcher objects

class py2neo.NodeMatcher(graph)[source]

Matcher for selecting nodes.

A NodeMatcher can be used to locate nodes that fulfil a specific set of criteria. Typically, a single node can be identified passing a specific label and property key-value pair. However, any number of labels and predicates supported by the Cypher WHERE clause are allowed.

For a simple equality match by label and property:

>>> from py2neo import Graph
>>> from py2neo.matching import *
>>> g = Graph()
>>> nodes = NodeMatcher(g)
>>> keanu = nodes.match("Person", name="Keanu Reeves").first()
>>> keanu
Node('Person', born=1964, name='Keanu Reeves')
Parameters:

graphGraph object on which to perform matches

iter(matcher)

Iterate through the matches, yielding the node ID for each one in turn.

len(matcher)

Count the matched nodes and return the number matched.

node_id in matcher

Determine whether a given node ID exists.

matcher[node_id]

Match and return a specific node by ID. This raises a KeyError if no such node can be found.

get(identity)[source]

Create a new NodeMatch that filters by identity and returns the first matched Node. This can be used to match and return a Node by ID.

>>> matches.get(1234)
Node('Person', name='Alice')

If no such Node is found, None is returned instead. Contrast with matcher[1234] which raises a KeyError if no entity is found.

match(*labels, **properties)[source]

Describe a basic node match using labels and property equality.

Parameters:
  • labels – node labels to match

  • properties – set of property keys and values to match

Returns:

NodeMatch instance

NodeMatch objects

class py2neo.NodeMatch(graph, labels=frozenset({}), predicates=(), order_by=(), skip=None, limit=None)[source]

Immutable set of node selection criteria.

iter(match)

Iterate through all matching nodes.

len(match)

Return the number of nodes matched.

all()[source]

Evaluate the selection and return a list of all matched Node objects.

Returns:

list of matching Node objects

New in version 2020.0.

count()[source]

Evaluate the selection and return a count of the number of matches.

Returns:

number of nodes matched

New in version 2020.0.

exists()[source]

Evaluate the selection and return True if at least one matched node exists.

Returns:

boolean indicating presence or absence of a match

New in version 2020.0.

first()[source]

Evaluate the match and return the first Node matched or None if no matching nodes are found.

Returns:

a single matching Node or None

limit(amount)[source]

Limit to at most amount nodes.

Parameters:

amount – maximum number of nodes to return

Returns:

refined NodeMatch object

order_by(*fields)[source]

Order by the fields or field expressions specified.

To refer to the current node within a field or field expression, use the underscore character _. For example:

match.order_by("_.name", "max(_.a, _.b)")
Parameters:

fields – fields or field expressions to order by

Returns:

refined NodeMatch object

skip(amount)[source]

Skip the first amount nodes in the result.

Parameters:

amount – number of nodes to skip

Returns:

refined NodeMatch object

where(*predicates, **properties)[source]

Refine this match to create a new match. The criteria specified for refining the match consist of predicates and properties. Conditions are individual Cypher expressions that would be found in a WHERE clause; properties are used as exact matches for property values.

To refer to the current node within a predicate expression, use the underscore character _. For example:

match.where("_.name =~ 'J.*'")

Simple property equalities can also be specified:

match.where(born=1976)
Parameters:
  • predicates – Cypher expressions to add to the WHERE clause

  • properties – exact property match keys and values

Returns:

refined NodeMatch object

Relationship matching

RelationshipMatcher objects

class py2neo.RelationshipMatcher(graph)[source]

Matcher for selecting relationships that fulfil a specific set of criteria.

Parameters:

graphGraph object on which to perform matches

iter(matcher)

Iterate through the matches, yielding the relationship ID for each one in turn.

len(matcher)

Count the matched relationships and return the number matched.

relationship_id in matcher

Determine whether a given relationship ID exists.

matcher[relationship_id]

Match and return a specific relationship by ID. This raises a KeyError if no such relationship can be found.

get(identity)[source]

Create a new RelationshipMatch that filters by identity and returns the first matched Relationship. This can be used to match and return a Relationship by ID.

>>> relationships.get(1234)
Relationship(...)

If no such Relationship is found, None is returned instead. Contrast with matcher[1234] which raises a KeyError if no entity is found.

match(nodes=None, r_type=None, **properties)[source]

Describe a basic relationship match using start and end nodes plus relationship type.

Parameters:
  • nodes – Sequence or Set of start and end nodes (None means any node); a Set implies a match in any direction

  • r_type

  • properties – set of property keys and values to match

Returns:

RelationshipMatch instance

RelationshipMatch objects

class py2neo.RelationshipMatch(graph, nodes=None, r_type=None, predicates=(), order_by=(), skip=None, limit=None)[source]

Immutable set of relationship selection criteria.

iter(match)

Iterate through all matching relationships.

len(match)

Return the number of relationships matched.

all()[source]

Evaluate the selection and return a list of all matched Relationship objects.

Returns:

list of matching Relationship objects

New in version 2020.0.

count()[source]

Evaluate the selection and return a count of the number of matches.

Returns:

number of relationships matched

New in version 2020.0.

exists()[source]

Evaluate the selection and return True if at least one matched relationship exists.

Returns:

boolean indicating presence or absence of a match

New in version 2020.0.

first()[source]

Evaluate the selection and return the first Relationship selected or None if no matching relationships are found.

Returns:

a single matching Relationship or None

limit(amount)[source]

Limit to at most amount relationships.

Parameters:

amount – maximum number of relationships to return

Returns:

refined RelationshipMatch object

order_by(*fields)[source]

Order by the fields or field expressions specified.

To refer to the current relationship within a field or field expression, use the underscore character _. For example:

match.order_by("_.weight", "max(_.a, _.b)")
Parameters:

fields – fields or field expressions to order by

Returns:

refined RelationshipMatch object

skip(amount)[source]

Skip the first amount relationships in the result.

Parameters:

amount – number of relationships to skip

Returns:

refined RelationshipMatch object

where(*predicates, **properties)[source]

Refine this match to create a new match. The criteria specified for refining the match consist of predicates and properties. Conditions are individual Cypher expressions that would be found in a WHERE clause; properties are used as exact matches for property values.

To refer to the current relationship within a predicate expression, use the underscore character _. For example:

match.where("_.weight >= 30")

Simple property equalities can also be specified:

match.where(since=1999)
Parameters:
  • predicates – Cypher expressions to add to the WHERE clause

  • properties – exact property match keys and values

Returns:

refined RelationshipMatch object

Applying predicates

Predicates other than basic equality can be applied to a match by using the built-in predicate functions.

For example, to match all nodes with a name that starts with “John”, use the STARTS_WITH function, which corresponds to the similarly named Cypher operator:

>>> nodes.match("Person", name=STARTS_WITH("John")).all()
[Node('Person', born=1966, name='John Cusack'),
 Node('Person', born=1950, name='John Patrick Stanley'),
 Node('Person', born=1940, name='John Hurt'),
 Node('Person', born=1960, name='John Goodman'),
 Node('Person', born=1965, name='John C. Reilly')]

The ALL and ANY functions can combine several other functions with an AND or OR operation respectively. The example below matches everyone born between 1964 and 1966 inclusive:

>>> nodes.match("Person", born=ALL(GE(1964), LE(1966))).all()
[Node('Person', born=1964, name='Keanu Reeves'),
 Node('Person', born=1965, name='Lana Wachowski'),
 Node('Person', born=1966, name='Kiefer Sutherland'),
 Node('Person', born=1966, name='John Cusack'),
 Node('Person', born=1966, name='Halle Berry'),
 Node('Person', born=1965, name='Tom Tykwer'),
 Node('Person', born=1966, name='Matthew Fox'),
 Node('Person', born=1965, name='John C. Reilly')]

Changed in 2020.0: the predicate system has been overhauled to provide a more idiomatic API.

Null check predicates

py2neo.IS_NULL()

Null value predicate.

This is equivalent to the Cypher expression x IS NULL.

py2neo.IS_NOT_NULL()

Non-null value predicate.

This is equivalent to the Cypher expression x IS NOT NULL.

Equality predicates

py2neo.EQ(value)

Equal value predicate.

This is equivalent to the Cypher expression x = value.

py2neo.NE(value)

Unequal value predicate.

This is equivalent to the Cypher expression x <> value.

Ordering predicates

py2neo.LT(value)

Lesser value predicate.

This is equivalent to the Cypher expression x < value.

py2neo.LE(value)

Lesser or equal value predicate.

This is equivalent to the Cypher expression x <= value.

py2neo.GT(value)

Greater value predicate.

This is equivalent to the Cypher expression x > value.

py2neo.GE(value)

Greater or equal value predicate.

This is equivalent to the Cypher expression x >= value.

String predicates

py2neo.STARTS_WITH(value)

String prefix predicate.

This is equivalent to the Cypher expression s STARTS WITH value.

>>> nodes.match("Person", name=STARTS_WITH("Kevin")).all()
[Node('Person', born=1958, name='Kevin Bacon'),
 Node('Person', born=1957, name='Kevin Pollak')]
py2neo.ENDS_WITH(value)

String suffix predicate.

This is equivalent to the Cypher expression s ENDS WITH value.

>>> nodes.match("Person", name=ENDS_WITH("Wachowski")).all()
[Node('Person', born=1967, name='Andy Wachowski'),
 Node('Person', born=1965, name='Lana Wachowski')]
py2neo.CONTAINS(value)

Substring predicate.

>>> nodes.match("Person", name=CONTAINS("eve")).all()
[Node('Person', born=1967, name='Steve Zahn'),
 Node('Person', born=1964, name='Keanu Reeves')]

This is equivalent to the Cypher expression s CONTAINS value.

py2neo.LIKE(regex)

Regular expression matching predicate. The regex can be a string or an pre-existing compiled Python re pattern.

>>> nodes.match("Person", name=LIKE("Ke.*n")).all()
[Node('Person', born=1958, name='Kevin Bacon'),
 Node('Person', born=1962, name='Kelly Preston')]

This is equivalent to the Cypher expression s =~ regex.

List predicates

py2neo.IN(value)

List membership predicate.

>>> nodes.match("Person", born=IN([1962, 1964, 1966])).all()
[Node('Person', born=1964, name='Keanu Reeves'),
 Node('Person', born=1962, name='Tom Cruise'),
 Node('Person', born=1962, name='Demi Moore'),
 Node('Person', born=1966, name='Kiefer Sutherland'),
 Node('Person', born=1962, name='Anthony Edwards'),
 Node('Person', born=1962, name='Kelly Preston'),
 Node('Person', born=1966, name='John Cusack'),
 Node('Person', born=1962, name="Rosie O'Donnell"),
 Node('Person', born=1966, name='Halle Berry'),
 Node('Person', born=1966, name='Matthew Fox')]

This is equivalent to the Cypher expression x IN list.

Connectives

py2neo.AND(*values)

Connective wherein all predicates must evaluate true.

>>> nodes.match("Person", born=AND(GE(1964), LE(1966))).all()
[Node('Person', born=1965, name='John C. Reilly'),
 Node('Person', born=1964, name='Keanu Reeves'),
 Node('Person', born=1965, name='Lana Wachowski'),
 Node('Person', born=1966, name='Kiefer Sutherland'),
 Node('Person', born=1966, name='John Cusack'),
 Node('Person', born=1966, name='Halle Berry'),
 Node('Person', born=1965, name='Tom Tykwer'),
 Node('Person', born=1966, name='Matthew Fox')]

This is equivalent to the Cypher expression (pred1 AND pred2 AND ...).

py2neo.OR(*values)

Connective wherein at least one predicate must evaluate true.

>>> nodes.match("Person", name=OR(STARTS_WITH("H"), ENDS_WITH("h"))).all()
[Node('Person', born=1960, name='Hugo Weaving'),
 Node('Person', born=1943, name='J.T. Walsh'),
 Node('Person', born=1941, name='Jim Cash'),
 Node('Person', born=1963, name='Helen Hunt'),
 Node('Person', born=1950, name='Howard Deutch'),
 Node('Person', born=1966, name='Halle Berry'),
 Node('Person', born=1985, name='Emile Hirsch')]

This is equivalent to the Cypher expression (pred1 OR pred2 OR ...).

py2neo.XOR(*values)

Connective wherein exactly one predicate must evaluate true.

>>> nodes.match("Person", name=XOR(STARTS_WITH("H"), ENDS_WITH("h"))).all()
[Node('Person', born=1960, name='Hugo Weaving'),
 Node('Person', born=1943, name='J.T. Walsh'),
 Node('Person', born=1941, name='Jim Cash'),
 Node('Person', born=1963, name='Helen Hunt'),
 Node('Person', born=1966, name='Halle Berry'),
 Node('Person', born=1985, name='Emile Hirsch')]

This is equivalent to the Cypher expression (pred1 XOR pred2 XOR ...).

Custom predicates

For predicates that cannot be expressed using one of the built-in functions, raw Cypher expressions can also be inserted into NodeMatch.where() method to refine the selection. Here, the underscore character can be used to refer to the node being filtered:

>>> nodes.match("Person").where("_.born % 10 = 0").all()
[Node('Person', born=1950, name='Ed Harris'),
 Node('Person', born=1960, name='Hugo Weaving'),
 Node('Person', born=1940, name='Al Pacino'),
 Node('Person', born=1970, name='Jay Mohr'),
 Node('Person', born=1970, name='River Phoenix'),
 Node('Person', born=1940, name='James L. Brooks'),
 Node('Person', born=1960, name='Annabella Sciorra'),
 Node('Person', born=1970, name='Ethan Hawke'),
 Node('Person', born=1940, name='James Cromwell'),
 Node('Person', born=1950, name='John Patrick Stanley'),
 Node('Person', born=1970, name='Brooke Langton'),
 Node('Person', born=1930, name='Gene Hackman'),
 Node('Person', born=1950, name='Howard Deutch'),
 Node('Person', born=1930, name='Richard Harris'),
 Node('Person', born=1930, name='Clint Eastwood'),
 Node('Person', born=1940, name='John Hurt'),
 Node('Person', born=1960, name='John Goodman'),
 Node('Person', born=1980, name='Christina Ricci'),
 Node('Person', born=1960, name='Oliver Platt')]

Ordering and limiting

As with raw Cypher queries, ordering and limiting can also be applied:

>>> nodes.match("Person").where(name=LIKE("K.*")).order_by("_.name").limit(3).all()
[Node('Person', born=1964, name='Keanu Reeves'),
 Node('Person', born=1957, name='Kelly McGillis'),
 Node('Person', born=1962, name='Kelly Preston')]