Skip to main content

Programmatically manipulate Neo4j Cypher language constructs

Project description

minicypher - Object representations of Neo4j Cypher query elements

minicypher is a set of classes that can be used together to create Python representations of Neo4j Cypher query statements. It allows the user to create syntactically correct Cypher statements in a less error-prone and more conceptual way by using Python, without having to manipulate strings, or keep track of Cypher variable names. It can automatically parameterize a statement, providing a dict of parameters and values.

Pypher is a more complete facility that does similar things in a nice way. There is less magic in minicypher, and its internal concepts may be slightly different. Unlike Pypher, minicypher is not at pains to mimic the declarative form of a Cypher statement. minicypher is more function-oriented.

Motivation

Suppose you want to create the following Cypher statement for execution

MATCH (a:Actor)-[:played_in]->(m:Movie)
WHERE a.name = "Sean Connery"
RETURN m.title as Title;

There are three clauses, MATCH, WHERE, and RETURN, in this statement. The use of variable m indicates that the value of the title property in the RETURN should come from the Movie node matched in the MATCH pattern. Variable a in the statement indicates that the Actor node matched in the MATCH pattern should be constrained by the equality in the WHERE clause.

In minicypher, you construct two node objects, one for the Movie and one for the Actor. These objects will be used in the contexts of the two clauses in which they appear. minicypher will render them in a statement appropriately.

from minicypher import *
actor = N('Actor',{'name':'Sean Connery'})
movie = N('Movie',{'title':''})

stmt = Statement(
         Match( R('played_in').anon().relate(actor.plain(), movie.plain()) ),
		 Where( actor.props['name'] ),
		 Return( movie.props['title'].As('Title') ))

When stmt is rendered as a string, e.g., when printed, it yields the query:

> print(stmt)
MATCH (n1:Actor)-[:played_in]->(n0:Movie) \
WHERE n1.name = 'Sean Connery' \
RETURN n0.title as Title

with dummy variables n0 and n1 correctly placed.

Entities, Clauses, Functions, Statements

Entities: Nodes, Relationships, and Properties

The basic idea is that a node, relationship, or property instance knows how to behave depending on where it shows up in a statement. Using the same instance in different parts of a statement will ensure that the variable name stays the same, for example. Variable names are provided automatically.

Constructors for entities:

Entity Constructor
Node N(label=,props=,As=,var=)
Relationship R(Type=,props=,As=,var=)
Property P(handle=,value=,As=,var=)

Properties are associated with a node or relationship as members of the .props attribute, a dict. Property instances can be provided with a value; this value is rendered in a statement depending on whether the property appears in a Cypher pattern, a Where clause, or a Return clause.

Example:

actor = N('Actor', P('name', 'Sean Connery'))

Then the property instance 'name' is accessed as actor.props["name"], and its value is at actor.props["name"].value.

In a Cypher MATCH pattern, a node or relationship may be represented in different ways - from anonymous entities, as in ()-[]->(), to entities with variable names and property maps specified, as in (m:Movie {title:"Goldeneye"})<-[r:acted_in]-(a:Actor {name:"Sean Connery"}). The modifier methods .anon(), .var(), .plain(), and .plain_var() provide control over what information is rendered in the final Statement.

This item is rendered as Notes
actor (n:Actor {name:"Sean Connery"}) Both label and property map are produced by default
actor.anon() (:Actor {name: "Sean Connery"}) Do not produce the variable
actor.var() (n {name: "Sean Connery"}) Do not produce the label (or relationship type)
actor.plain() (n:Actor) Do not produce the property map
actor.plain_var() (n) Only produce the variable name

Clauses and Statements

Clauses correspond to parts of a Cypher statement prefaced by a keyword, such as MATCH, WHERE, or RETURN. Clause instances provide a context for rendering their arguments (nodes, relationships, properties) so that they try to "do what you mean."

The Match() clause treats its arguments as elements of a Cypher graph pattern. If nodes or relationships have properties with values set, the property map is rendered by default. See the table above to tweak the pattern production with modifier methods.

The Where() clause considers its arguments as participating in a boolean condition. If a property instance on a node or relationship has a set value, then in a Where() clause, an equals condition for the property is produced:

>>> n = N('', [ P('this', 1), P('that', 2)])
>>> print(Where(n))
WHERE n0.this = 1 AND n0.that = 2

Override this behavior by referencing the properties directly.

>>> print(Where(n.props['this']))
WHERE n0.this = 1
>>> print(Where(n.props['that'].with_value(3)))
WHERE n0.that = 3

The Return() and other clauses render their arguments as variables, or as aliases if the .As attribute is set to a desired alias.

Functions

Cypher functions, such as count(), labels(), ltrim(), and others that appear in conditions or return clauses can be produced with the Func class. Instances will know how to render themselves and their arguments depending on context and the presence of AS aliases.

To render a function like labels(), with a simple name and argument(s) in parens, use the name parameter in a Func() constructor:

>>> n = N('this:that',var='node')
>>> f = Func(n, name='labels')
>>> print(f)
labels(node)
>>> print(f.As('lbls'))
labels(node) AS lbls
>>> print(Func(n, name='labels').As('lbls').substitution())
lbls

Additional arguments will be added as expected:

>>> print(Func(n, "x", "y", name="location"))
location(n0,x,y)

A few functions with special rendering are provided: And, Or, Not, is_null, is_not_null:

>>> n = N(props=[P("this",1)])
>>> m = N(props=[P("that",2)])
>>> print(Where(AND(n, m)))
WHERE n0.this = 1 AND n1.that = 2

>>> print(Where(is_not_null(n)))
WHERE n0 IS NOT NULL

The Cat (concatentate) class can be used to construct other infix functions (like >, <) appropriately:

>>> val = 1
>>> print(Where(Cat(n.props['this'],f"> {val}")))
WHERE n0.this > 1

Statements

Clauses are strung together in order as arguments to a Statement() constructor. When printed or otherwise used as a string, a Statement instance yields a Cypher query. The Statement instance can also parameterize the statement and provide a dict of params and values.

Plain strings as arguments to clause constructors and Statement() will be rendered verbatim.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

minicypher-0.1.3.tar.gz (12.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

minicypher-0.1.3-py3-none-any.whl (11.7 kB view details)

Uploaded Python 3

File details

Details for the file minicypher-0.1.3.tar.gz.

File metadata

  • Download URL: minicypher-0.1.3.tar.gz
  • Upload date:
  • Size: 12.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.12.9

File hashes

Hashes for minicypher-0.1.3.tar.gz
Algorithm Hash digest
SHA256 1c8f6e6767914483971173a6207a6e479aa3ae69fe90fad6610fa2788b16b25c
MD5 20ebcd432dcbd09e57eab7a923a18f01
BLAKE2b-256 0ea57bb8893309349d73da6ee0784f05a046da417a6e9ad4a625df1139d18171

See more details on using hashes here.

File details

Details for the file minicypher-0.1.3-py3-none-any.whl.

File metadata

  • Download URL: minicypher-0.1.3-py3-none-any.whl
  • Upload date:
  • Size: 11.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.12.9

File hashes

Hashes for minicypher-0.1.3-py3-none-any.whl
Algorithm Hash digest
SHA256 f2327719348b4baef31da991996124c6ccadbf207f90398a15d7142407082ebf
MD5 945cf2ac7419c549c6860b3b859e0e7f
BLAKE2b-256 64c7acfdc94e1cb061312492331a865aee9bd421f1eb3ecd5404de0ab370f4a7

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page