Overview Defining a Model Instances Creating Nodes and Relationships Merging Nodes and Relationships Updating Nodes and Relationships Deleting Nodes Deleting Relationships Finding Nodes and Relationships Hooks Temporary Databases
QueryBuilderParameters['MatchI']
A literal string will be used as is.
1linkconst queryBuilder = new QueryBuilder()
2link .match('(a:A)'); /* --> literal string to use */
3link
4linkconsole.log(queryBuilder.getStatement()); // MATCH (a:A)
5linkconsole.log(queryBuilder.getBindParam().get()); // {}
This has the benefit of being able to make the match optional.
1linkconst queryBuilder = new QueryBuilder().match({
2link /* --> literal string to use */
3link literal: '(a:A)',
4link /* --> (optional) whether this match will be "optional" */
5link optional: true,
6link});
7link
8linkconsole.log(queryBuilder.getStatement()); // OPTIONAL MATCH (a:A)
9linkconsole.log(queryBuilder.getBindParam().get()); // {}
An object can be used to easily match a node with an identifier, label, where.
1linkconst queryBuilder = new QueryBuilder().match({
2link /* --> (optional) the identifier of the node */
3link identifier: 'n',
4link /* --> (optional) the label of the node */
5link label: 'MyLabel',
6link /* --> (optional) where parameters for matching this node. They are of the "WhereParamsI" type */
7link where: { // @see [Where Parameters](../Where-Parameters.md)
8link id: '20',
9link },
10link /* --> (optional) whether this match will be "optional" */
11link optional: true,
12link});
13link
14linkconsole.log(queryBuilder.getStatement()); // OPTIONAL MATCH (n:MyLabel { id: $id })
15linkconsole.log(queryBuilder.getBindParam().get()); // { id: '20' }
All those attributes are optional. The matching node will use every attribute which is given. If none of them are given, the statement will equal to MATCH ().
A Model can be used instead of the label attribute. In this case, the Model's label will be used.
1linkconst queryBuilder = new QueryBuilder().match({
2link /* --> (optional) */
3link identifier: 'n',
4link /* --> (optional) the Model whose label will be used */
5link model: MyModel,
6link});
7link
8link/* --> assuming MyModel.getLabel() returns `MyModelLabel` */
9linkconsole.log(queryBuilder.getStatement()); // MATCH (n:`MyModelLabel`)
10linkconsole.log(queryBuilder.getBindParam().get()); // { }
All Where operators (Op.gt, Op.gte, Op.lt, Op.lte, Op.ne, Op.in, Op._in, Op.contains) are supported in the where parameter. The QueryBuilder automatically separates equality checks (which use Neo4j's bracket syntax) from other operators (which use a WHERE clause).
1linkconst queryBuilder = new QueryBuilder().match({
2link identifier: 'u',
3link label: 'User',
4link where: {
5link status: 'active', // Goes to bracket syntax: { status: $status }
6link age: { [Op.gte]: 18 }, // Goes to WHERE clause: WHERE u.age >= $age
7link },
8link});
9link
10link// Result: MATCH (u:User { status: $status }) WHERE u.age >= $age
11linkconsole.log(queryBuilder.getStatement());
12link// { status: 'active', age: 18 }
13linkconsole.log(queryBuilder.getBindParam().get());
The same applies to relationships in related patterns:
1linkconst queryBuilder = new QueryBuilder().match({
2link related: [
3link { identifier: 'u', label: 'User' },
4link {
5link direction: 'out',
6link name: 'FOLLOWS',
7link identifier: 'r',
8link where: { since: { [Op.gte]: 2020 } },
9link },
10link { identifier: 'p', label: 'Post' },
11link ],
12link});
13link
14link// Result: MATCH (u:User)-[r:FOLLOWS]->(p:Post) WHERE r.since >= $since
15linkconsole.log(queryBuilder.getStatement());
Note: When using non-equality operators, the WHERE clause needs to reference the node or relationship. If no identifier is provided, one is automatically generated (e.g.,
__nfor nodes,__rfor relationships). See Where Parameters for more details on operators.
You can pass a custom BindParam instance to the QueryBuilder constructor. This is useful when you want to share bind parameters across multiple queries or control parameter naming:
1linkimport { BindParam } from 'neogma';
2link
3linkconst bindParam = new BindParam();
4link
5linkconst queryBuilder = new QueryBuilder(bindParam).match({
6link label: 'Node',
7link where: { age: { [Op.gt]: 18 } },
8link});
9link
10link// The auto-generated identifier uses the shared BindParam
11link// Result: MATCH (__n:Node) WHERE __n.age > $age
12linkconsole.log(queryBuilder.getStatement());
13link
14link// Access bind parameters from either reference
15linkconsole.log(bindParam.get()); // { age: 18 }
16linkconsole.log(queryBuilder.getBindParam().get()); // { age: 18 }
By using the multiple attribute and an array of nodes, multiple nodes can be matched.
1linkconst queryBuilder = new QueryBuilder().match({
2link multiple: [
3link /* --> each entry has the same type as matching with a single object, like in the examples above */
4link {
5link identifier: 'a',
6link model: ModelA,
7link where: {
8link id: '20',
9link },
10link },
11link {
12link identifier: 'b',
13link },
14link ],
15link});
16link
17link/* --> assuming MyModel.getLabel() returns `MyModelLabel` */
18linkconsole.log(queryBuilder.getStatement()); // MATCH (a:`MyModelLabel` { id: $id }), (b)
19linkconsole.log(queryBuilder.getBindParam().get()); // { id: '20' }
By using the related attribute and an array of alternating node-relationship objects, a match between them is created.
1linkconst queryBuilder = new QueryBuilder().match({
2link related: [
3link /* --> each even entry is a "node" object, as defined above */
4link {
5link identifier: 'a',
6link model: ModelA,
7link where: {
8link nodeProp: '20',
9link },
10link },
11link /* --> each odd entry is a "relationship" object */
12link {
13link /* --> the direction of the relationship, from the node above towards the one below */
14link direction: 'out', // --> 'out' or 'in' or 'none'
15link /* --> (optional) name of the relationship */
16link name: 'RelationshipName',
17link /* --> (optional) identifier of the relationship */
18link identifier: 'r',
19link /* --> (optional) where parameters for matching this relationship. They are of the "WhereParamsI" type */
20link where: {
21link relProp: 1,
22link },
23link /* --> (optional) minimum hops for a variable length relationship */
24link minHops: 1,
25link /* --> (optional) maximum hops for a variable length relationship. The value Infinity can be used for no limit on the max hops */
26link maxHops: 1,
27link },
28link /* --> the final entry must be a node */
29link {
30link identifier: 'b'
31link }
32link ],
33link});
34link
35link/* --> assuming MyModel.getLabel() returns `MyModelLabel` */
36link// MATCH (a:`MyModelLabel` { nodeProp: $nodeProp })-[r:RelationshipName { relProp: $relProp }]->(b)
37linkconsole.log(queryBuilder.getStatement());
38link// { nodeProp: '20', relProp: 1 }
39linkconsole.log(queryBuilder.getBindParam().get());
A more elaborate example:
1linkconst queryBuilder = new QueryBuilder().match({
2link related: [
3link {
4link identifier: 'a',
5link model: ModelA,
6link where: {
7link nodeProp: '20',
8link },
9link },
10link /* --> The static `getRelationshipByAlias` of a model can be used as a shortcut. */
11link ModelA.getRelationshipByAlias('Relationship1'),
12link {
13link identifier: 'b'
14link },
15link {
16link direction: 'in'
17link },
18link {
19link ...ModelA.getRelationshipByAlias('Relationship2'),
20link identifier: 'r2'
21link where: {
22link relProp: 2
23link }
24link },
25link {}
26link ],
27link});
28link
29link/* --> assuming MyModel.getLabel() returns `MyModelLabel` */
30link/* --> assuming 'Relationship1' has configuration: direction: 'out', name: 'Relationship1Name' */
31link/* --> assuming 'Relationship1' has configuration: direction: 'in', name: 'Relationship2Name' */
32link// --> MATCH (a:`MyModelLabel` { nodeProp: $nodeProp })-[:Relationship1Name]->(b)<-[r2:Relationship2Name { relProp: $relProp }]-()
33linkconsole.log(queryBuilder.getStatement());
34link// --> { nodeProp: '20', relProp: 2 }
35linkconsole.log(queryBuilder.getBindParam().get());
For expected behavior, the first and last elements must be a node object.