Giter VIP home page Giter VIP logo

cypher-query-builder's Introduction

Cypher Query Builder

Build Status Coverage Status Commitizen friendly

Become a patreon

A flexible and intuitive query builder for Neo4j and Cypher. Write queries in Javascript just as you would write them in Cypher.

  • Easy to use fluent interface
  • Support for streaming records using observables
  • Full Typescript declarations included in package
let results = await db.matchNode('user', 'User', { active: true })
  .where({ 'user.age': greaterThan(18) })
  .with('user')
  .create([
    cypher.node('user', ''),
    cypher.relation('out', '', 'HasVehicle'),
    cypher.node('vehicle', 'Vehicle', { colour: 'red' })
  ])
  .ret(['user', 'vehicle'])
  .run();

// Results:
// [{
//   user: {
//     identity: 1234,
//     labels: [ 'User' ],
//     properties: { ... },
//   },
//   vehicle: {
//     identity: 4321,
//     labels: [ 'Vehicle' ],
//     properties: { ... },
//   },
// }]

Contents

Quick start

Installation

npm install --save cypher-query-builder

or

yarn add cypher-query-builder

Importing

CommonJS/Node

const cypher = require('cypher-query-builder');
// cypher.Connection
// cypher.greaterThan
// ....

ES6

import { Connection, greaterThan } from 'cypher-query-builder';

Connecting

const cypher = require('cypher-query-builder');

// Make sure to include the protocol in the hostname
let db = new cypher.Connection('bolt://localhost', {
  username: 'root',
  password: 'password',
});

Cypher query builder uses the official Neo4j Nodejs driver over the bolt protocol in the background so you can pass any values into connection that are accepted by that driver.

Querying

ES6

db.matchNode('projects', 'Project')
  .return('projects')
  .run()
  .then(function (results) {
    // Do something with results
  });

ES2017

const results = await db.matchNode('projects', 'Project')
  .return('projects')
  .run();

run will execute the query and return a promise. The results are in the standardish Neo4j form an array of records:

const results = [
  {
    projects: {
      // Internal Neo4j node id, don't rely on this to stay constant.
      identity: 1,

      // All labels attached to the node
      labels: [ 'Project' ],

      // Actual properties of the node.
      // Note that Neo4j numbers will automatically be converted to
      // Javascript numbers. This may cause issues because Neo4j can
      // store larger numbers than can be represented in Javascript.
      // This behaviour is currently in consideration and may change
      // in the future.
      properties: { name: 'Project 1' },
    },
  },
  // ...
]

You can also use the stream method to download the results as an observable.

const results = db.matchNode('project', 'Project')
  .ret('project')
  .stream();

results.subscribe(row => console.log(row.project.properties.name));

Processing

To extract the results, you can use ES5 array methods or a library like lodash:

// Get all the project nodes (including their id, labels and properties).
let projects = results.map(row => row.projects);

// Get just the properties of the nodes
let projectProps = results.map(row => row.projects.properties);

Documentation

All the reference documentation can be found here. However, the two most useful pages are probably:

  • The Connection class, for details on creating and using a connection.
  • The Query class, for details on all the available clauses, and building and running queries.

Contributing

Please feel free to submit any bugs or questions you may have in an issue. I'm very open to discussing suggestions or new ideas so don't hesitate to reach out.

Maintaining the library does take some time out of my schedule so if you'd like to show your appreciation please consider donating. Even the smallest amount is really encouraging.

Become a patreon

License

MIT License

Copyright (c) 2018 James Ferguson

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

cypher-query-builder's People

Contributors

austince avatar bboure avatar greenkeeper[bot] avatar jamesdcode avatar jamesfer avatar krystxf avatar purplemana avatar semantic-release-bot avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

cypher-query-builder's Issues

support adding properties from maps

Hi,

Just noticed that setVariables() supports override: true but it expands all the variables rather than just passing parameters while setValues() doesn't support adding properties.

What I expect is

SET data += $data

For example:

const data = {
  a: 'some string',
  b: 1234
}

With setVariables({ data: data }), it goes:

SET
  data.a += some string, // as your document said, the string won't be escaped
  data.b += 1234

With setValues({ data: data }), it goes:

SET data = $data

An in-range update of rollup is breaking the build 🚨

The devDependency rollup was updated from 1.27.13 to 1.27.14.

🚨 View failing branch.

This version is covered by your current version range and after updating it in your project the build failed.

rollup is a devDependency of this project. It might not break your production code or affect downstream projects, but probably breaks your build or test tools, which may prevent deploying or publishing.

Status Details
  • ❌ continuous-integration/travis-ci/push: The Travis CI build failed (Details).

FAQ and help

There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.


Your Greenkeeper Bot 🌴

An in-range update of semantic-release is breaking the build 🚨

The devDependency semantic-release was updated from 15.13.32 to 15.14.0.

🚨 View failing branch.

This version is covered by your current version range and after updating it in your project the build failed.

semantic-release is a devDependency of this project. It might not break your production code or affect downstream projects, but probably breaks your build or test tools, which may prevent deploying or publishing.

Status Details
  • ❌ continuous-integration/travis-ci/push: The Travis CI build failed (Details).

Release Notes for v15.14.0

15.14.0 (2019-12-21)

Features

  • pass envi-ci values to plugins context (a8c747d)
Commits

The new version differs by 2 commits.

  • a8c747d feat: pass envi-ci values to plugins context
  • fc70726 chore: add Mockserver generated file to gitignore

See the full diff

FAQ and help

There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.


Your Greenkeeper Bot 🌴

Support for COLLECT(node) in the return clause

When I attempt to use COLLECT on a return node, the Transformer class currently returns null. I would like to get the array of transformed values - or alternatively specify a custom transformer with the connection initializer.

Thanks for all the great work!

An in-range update of @types/chai-as-promised is breaking the build 🚨

The devDependency @types/chai-as-promised was updated from 7.1.1 to 7.1.2.

🚨 View failing branch.

This version is covered by your current version range and after updating it in your project the build failed.

@types/chai-as-promised is a devDependency of this project. It might not break your production code or affect downstream projects, but probably breaks your build or test tools, which may prevent deploying or publishing.

Status Details
  • ❌ continuous-integration/travis-ci/push: The Travis CI build failed (Details).

FAQ and help

There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.


Your Greenkeeper Bot 🌴

Cannot find module '../node_modules/lodash/isArray.js'

Hello, I've been using this great library for a while now. I recently tried to fork an existing app and can't get it to work. I'm receiving the following error. Thanks for your work on this library and thanks for taking time to review my issue.

`internal/modules/cjs/loader.js:582
throw err;
^

Error: Cannot find module '../node_modules/lodash/isArray.js'
at Function.Module._resolveFilename (internal/modules/cjs/loader.js:580:15)
at Function.Module._load (internal/modules/cjs/loader.js:506:25)
at Module.require (internal/modules/cjs/loader.js:636:17)
at require (internal/modules/cjs/helpers.js:20:18)
at Object. (C:_\myappname\node_modules\cypher-query-builder\dist\cjs5.js:7:32)
at Module._compile (internal/modules/cjs/loader.js:688:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:699:10)
at Module.load (internal/modules/cjs/loader.js:598:32)
at tryModuleLoad (internal/modules/cjs/loader.js:537:12)
at Function.Module._load (internal/modules/cjs/loader.js:529:3)`

An in-range update of babel7 is breaking the build 🚨

There have been updates to the babel7 monorepo:

    • The devDependency @babel/core was updated from 7.7.5 to 7.7.7.

🚨 View failing branch.

This version is covered by your current version range and after updating it in your project the build failed.

This monorepo update includes releases of one or more dependencies which all belong to the babel7 group definition.

babel7 is a devDependency of this project. It might not break your production code or affect downstream projects, but probably breaks your build or test tools, which may prevent deploying or publishing.

Status Details
  • ❌ continuous-integration/travis-ci/push: The Travis CI build failed (Details).

FAQ and help

There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.


Your Greenkeeper Bot 🌴

The automated release is failing 🚨

🚨 The automated release from the master branch failed. 🚨

I recommend you give this issue a high priority, so other packages depending on you could benefit from your bug fixes and new features.

You can find below the list of errors reported by semantic-release. Each one of them has to be resolved in order to automatically publish your package. I’m sure you can resolve this πŸ’ͺ.

Errors are usually caused by a misconfiguration or an authentication problem. With each error reported below you will find explanation and guidance to help you to resolve it.

Once all the errors are resolved, semantic-release will release your package the next time you push a commit to the master branch. You can also manually restart the failed CI job that runs semantic-release.

If you are not sure how to resolve this, here is some links that can help you:

If those don’t help, or if this issue is reporting something you think isn’t right, you can always ask the humans behind semantic-release.


The push permission to the Git repository is required.

semantic-release cannot push the version tag to the branch master on remote Git repository with URL github:jamesfer/cypher-query-builder.

Please refer to the authentication configuration documentation to configure the Git credentials on your CI environment and make sure the repositoryUrl is configured with a valid Git URL.


Good luck with your project ✨

Your semantic-release bot πŸ“¦πŸš€

Stream method on queries that returns an observable

The Neo4j driver supports streaming results from the database as they arrive allowing them to be transformed and processed immediately. The Query and Connection classes should both support a stream method that will return an observable of the results of the query.

How to add conditions on one property with AND between

Seems like a stupid question, but how do I generate a query like this one:

MATCH (someNode:SomeLabel) 
WHERE someNode.someProperty > 1 AND someNode.someProperty < 100

I want to be able to add any type of conditions, not just < and >, so please don't tell me to use between πŸ˜›

Since you need to pass an object to and, it seems like there's no way to combine multiple conditions on a single property

Cannot specify query return type with strict keys

Because the generic passed to run/stream/first is wrapped in a Dictionary, I cannot specify the object being returned.

For example,

const orgFromNode = (node: Node<Organization>) =>
  Organization.from(node.properties);

const orgNode = await q
  .matchNode('org', 'Organization')
  .return('org')
  .first();
return orgFromNode(orgNode);
TS2345: Argument of type 'Dictionary<any>' is not assignable to parameter of type 'Node<Organization>'.
  Type 'Dictionary<any>' is missing the following properties from type 'Node<Organization>': identity, labels, properties

IMO, Dictionary types are pretty worthless since you can't specify their associated keys. All keys could be any of the value types.

const record = {} as Dictionary<string | boolean | DateTime>;
record.updatedAt; // this a DateTime but TS thinks it could be a boolean or string as well
record.active; // this a boolean but TS thinks it could be a DateTime or string as well

It would be helpful if this wrapping is removed so one can specify the actual return type. i.e.

const orgNode = await q
  .matchNode('org', 'Organization')
  .return('org')
  .first<Node<Organization>>()

And Dictionary types could still be used by users, just explicitly now.
I know this is probably considered a breaking change πŸ™


On a positive note, I'm loving the library and it's design. Thanks for your hard work 🀝

plain object return is not supported

db
  .matchNode('foo', 'Foo', { id: "123" })
  .with(['foo', 'foo {.*} AS snapshot'])
  .return(['foo', 'snapshot'])

leads to

MATCH (foo:Foo { id: "123" }) WITH foo, foo {.*} AS snapshot RETURN foo, snapshot

The result snapshot will be null since the raw response won't be identity, labels, and properties but the object itself.

Assign MATCH query to variable

Is it possible to assign a query to a variable ?
For instance
MATCH p=(n:Node)-[r:REL]->(x:Node)
RETURN p

I would like to be able to assign to and access 'p' in the following example

db.match([
node('u', 'User', {id: '333333'}),
relation('out', ['MEMBER_OF_GROUP','HAS_REPORT_ROLE'],'*'),
node('r', 'Role', {allowed_delete: true})
]).return('count(u) > 0 as authorised')
.run()
.then(function (results) {
l.info(Is Authorised: + JSON.stringify(results[0]));
});

Question: relationship between existing nodes

Hi, I like this library, makes things easy. Could you please provide an example on how to add a relationship between two existing nodes?
I tries this:
const query = this.db.match([ node("a", this.modelType.constructor.name, {uuid: uuidFrom}), node("b", new toType().constructor.name, {uuid: uuidTo}) ]).create([ node("a"), relation("out", :${name}), node("b") ]);
but this results in
MATCH (a:User { uuid: '2c0d4196-0851-4ae2-b764-37696bd52a20' })(b:Token { uuid: '98a4551c-326d-417e-9f80-54151fb5b6e0' }) CREATE (a)-[:HasToken]->(b);
there is a comma missing between node a and b in the MATCH operation.

Thank you!

Later edit:
I finally managed to do it with this query:
const query = this.db.matchNode("a", this.modelType.constructor.name, {uuid: uuidFrom}) .matchNode("b", new toType().constructor.name, {uuid: uuidTo}) .create([ node("a"), relation("out", rel:${name}), node("b") ]);
It seems to be what I need. Do I miss something here? Maybe there are some performance issues because of the two matches?

Add literal function

Sometimes it's handy to be able insert literal sections of a query into other clauses. Currently it's not possible to do this meaning if there is no clause function that fits your use-case you have to resort to the raw() function.

Where clause seems to cause issues with parameter bag

We are using the .where() method to fetch nodes like so:
existingDataQuery.match([ node('a', Attribute.getLabel()), InstanceValue.getAttributeRelationship(false), InstanceValue.getEmptyNode('iv') ]) .where({ 'ID(a)': attribute.id }) .return(['iv']).limit(1);

We were noticing that there were no results returned for this query (even though we should see something). Running .toString() seems to return the correct query:
MATCH (a:Attribute)<-[:IS_VALUE_OF]-(iv:InstanceValue) WHERE ID(a) = $idA RETURN iv LIMIT 1;

When we run .interpolate() to see the parameters dropped in we see a problem:
MATCH (a:Attribute)<-[:IS_VALUE_OF]-(iv:InstanceValue) WHERE ID(a) = 9882 RETURN iv LIMIT 1;

The number value on the end of the parameter bag property name seems to be left at the end of the id parameter. See the attached images for an example.
example tostring
parameter bag
incorrect parameter value

Cannot create with multiple patterns

Following snippet would throw an error:

builder.create([
  [
    node('userA', 'User', { id: 'xxx' }),
    relation('out', ['HAS']),
    node('stuff', 'Stuff', { foo: 'bar' })
  ],
  [
    node('userA'),
    relation('out', ['LIKE']),
    node('userB', 'User', { id: 'yyy' }),
  ]
])

which the expected should be

CREATE (userA:User { id: 'xxx' })-[:HAS]->(stuff:Stuff { foo: 'bar' }), (userA)-[:LIKE]->(userB:User { id: 'yyy' })

Rather it throws an error TypeError: Cannot read property 'setExpandedConditions' of undefined

I think the bug is here

ReferenceError: node is not defined

Hi James,

I've been playing with your query-builder, but stumbled upon a few problems:

  1. Whenever I try to implement a standalone query like
query.merge([
  node('user', 'User', { id: 1 }),
  relation('out', 'rel', 'OwnsProject'),
  node('project', 'Project', { id: 20 }),
])

I get a
ReferenceError: node is not defined.

  1. Importing cypher does not work for me for some reason.
import cypher from 'cypher-query-builder'
console.log(cypher) // undefined 

So I can't get 'node'/'relation' functions to work (either standalone, or as method of cypher).
How do I import cypher? Or, rather, where do I get 'node' and 'relation' functions from?

  1. This query works perfectly fine
db.matchNode('stuff', 'Stuff')
    .return('stuff')
    .run()
    .then(result => console.log(result))

Many thanks!

Improve readme

  • Expand documentation section
  • Add paragraph about donations
  • Add paragraph about contributions
  • Add table of contents

list return support

Just tried return a list, seems a list result is not well handled.

await db.return('range(1, 50)').run()
// { "range(1, 50)": null }

Patterns or raw conditions in where clauses

Hi, thanks a lot for this library, it really cleaned up the logic of my recommendation engine :)

One issue I encountered though is that it doesn't seem possible to use patterns in where clauses such as described here.
I had to use qb.raw(), but it doesn't fit nicely in it as I have to determine wether .where was already called or not:

const hasWhereClause = !!filter && !!filter.resourceTypeIn;
 if (hasWhereClause) {
	    q.where({
	      r: {
	       type: inArray(filter.resourceTypeIn),
	      },
	    });
	}
	q.raw(`${hasWhereClause ? ' AND ' : 'WHERE '}(u)-[:CONSUMED]->(r)`);

Am I missing something, is there a better way to do it already ?

Also if supporting patterns in where conditions is too complex, maybe just adding the ability to add raw conditions in .where() would bring more flexibility already: it would also allow things like
toLower(r.name) CONTAINS toLower($query).

Let me know what you think !

between does not generate valid cypher

Current:

MATCH (n:Label)
WHERE n.date <= $upper,n.date >= $lower
RETURN n;

Invalid input ',': expected an identifier character, whitespace, '.',

Expected:

MATCH (n:Label)
WHERE $lower <= n.date <= $upper
RETURN n;

MERGE clause support?

Great work! πŸ‘

My project has started to use neo4j and I had begun to try this builder today.
May I know if there's any plan to support MERGE clause? It will be great to see this clause being implemented.

Keep it up!

Raw method should accept template strings

query.raw(raw `MATCH (person { name: ${name} })`)
// MATCH (person { name: $parameter })

All parameters passed to the query will be converted into query parameters. This would mean that queries won't be able to be built dynamically using template strings as some parts of cypher don't support parameters, eg.

// Invalid
query.raw(raw `MATCH (person { ${prop}: ${name} })`)
// MATCH (person { $paramter: $parameter2 })

Most of the time, dynamically building queries is to be avoided as Neo4j cannot optimise them as well, so this shouldn't be a big issue.

The raw method should return a query object like the one that is returned from query.buildQueryObject. The raw method will need to be overloaded to accept an object as the first parameter.

An in-range update of @types/node is breaking the build 🚨

The dependency @types/node was updated from 12.7.0 to 12.7.1.

🚨 View failing branch.

This version is covered by your current version range and after updating it in your project the build failed.

@types/node is a direct dependency of this project, and it is very likely causing it to break. If other packages depend on yours, this update is probably also breaking those in turn.

Status Details
  • ❌ continuous-integration/travis-ci/push: The Travis CI build could not complete due to an error (Details).

FAQ and help

There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.


Your Greenkeeper Bot 🌴

An in-range update of tslib is breaking the build 🚨

The dependency tslib was updated from 1.11.0 to 1.11.1.

🚨 View failing branch.

This version is covered by your current version range and after updating it in your project the build failed.

tslib is a direct dependency of this project, and it is very likely causing it to break. If other packages depend on yours, this update is probably also breaking those in turn.

Status Details
  • ❌ continuous-integration/travis-ci/push: The Travis CI build could not complete due to an error (Details).

Release Notes for tslib 1.11.1

This release updates tslib's declaration files so that users don't have to include declarations for WeakMap in their compilation.

Commits

The new version differs by 7 commits.

  • c1f87f7 Update version to '1.11.1'.
  • 5d26e24 Merge pull request #94 from microsoft/remove-weakmap
  • 418ee9c Fix return type of 'get'
  • b75bff8 Restore minimal type safety using a type literal
  • 9c92f58 Remove reference to WeakMap from tslib.d.ts
  • 364f0ec Merge pull request #90 from alan-agius4/patch-1
  • f6b75b4 build: exclude github workflows from npm package

See the full diff

FAQ and help

There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.


Your Greenkeeper Bot 🌴

Transformation of Temporal type

Hi,

I am experimenting with this package and it all looks promising. Thank you for the hard work!

I am running across a small issue though.
I am using neo4j date() and datetime() types in some properties.

When getting the result back from neo4j in a query, those properties come back as instances of neo4jDriver.v1.types.Date and neo4jDriver.v1.types.DateTime (see Temporal types).

However, when going through the transformer, they get transformed into standard objects here.

This means that I cannot use neo4jDriver.v1.isDate or neo4jDriver.v1.isDateTime anymore on them later on in my code for custom handling (in my case I use them to determine how to format them).

I would expect the transformer to either:

  • transform them into a Date object
  • return a formatted string (based on the type)
  • return them as-is

In fact, I am thinking that it would also be great to be able to inject a custom Transformer into the Connection. That would allow custom transformations.
In the case of date objects, it might be useful for localization, for example.

I haven't tested yet, but similar issues will likely happen with Duration, Type, Localtime, Point, etc.
See also https://neo4j.com/docs/driver-manual/1.7/cypher-values/#driver-neo4j-type-system

What do you think?

Thanks you

connectionAcquisitionTimeout

Hello,

Can you add provision of following parameter connectionAcquisitionTimeout in Connection class under the driverConfig:{}. I face following error:

Neo4jError: Connection acquisition timed out in 60000 ms

Also, if possible, one more parameter MaxConnectionPoolSize. The details of these parameters are available at 2.4.3. Connection pool management

Many Thanks

options for setValues doesn't work

Either

setValues({ foo: foo }, { override: true }) // foo is an object

or

setValues({ foo: foo }, true) // foo is an object

are sending out

SET foo = $foo

BTW, I think default value should be { override: false } to be compatible with previous versions

SetValues gives unexpected results

  public async update(id: string, card: Card): Promise<Card> {
    const results = await this.db
      .matchNode('card', 'Card')
      .where({
        'card.id': id
      })
      .setValues({
        'card.title': card.title,
        'card.type': card.type,
        'card.isActive': card.isActive,
      })
      .return('card')
      .run();
    return CardService.map(results)[0];
  }

produces this error:

Invalid input '+': expected whitespace, comment, '(', '.' or '=' (line 3, column 16 (offset: 53)) "SET card.title += $cardTitle, card.type += $cardType, card.isActive += $cardIsActive"
                ^
Neo4jError: Invalid input '+': expected whitespace, comment, '(', '.' or '=' (line 3, column 16 (offset: 53))
"SET card.title += $cardTitle, card.type += $cardType, card.isActive += $cardIsActive"

I assume this is a bug and not a feature? Ima go ahead and remove that '+' sign and shoot you a pull request! On the other hand Ima not set you a pr. I got no clue where the override is set to true in:

  setValues(values: Dictionary<any>, override?: boolean) {
    return this.chain(this.wrap(new Set({ values }, { override })));
  }

Ive forked it and ill hack the override: false for now so I can continue... but great work btw thank you so much for that!

Support storing match pattern in a variable

When using MATCH, the path pattern can be stored in a variable for use in FOREACH clauses or other functions.

Possible implementation could be:

query.match('path', [
  node('person'),
  relation('out', [ 'FriendsWith' ]),
  node('friend'),
])
// MATCH path = (person)-[:FriendsWith]->(friend)

Behaviour of where operators is inconsistent

According to the where operator types xor and or must accept an array of NodeConditions, Conditions or a single Condition.

This means you can do things like

query.where({
  age: xor([greaterThan(65), lessThan(12)]),
})

However, the and operator only accepts NodeConditions or Conditions. So you wouldn't be able to do the same thing.

I think and should be able to accept a Condition argument, which means that it probably needs to accept array properties as well. To make things entirely consistent, we should consider make all operators accept AnyConditions and then just use the operator to combine the outer most structure so:

query.where({ age: and([lessThan(65), greaterThan(12)])
// becomes
// WHERE age < 65 AND age > 12

query.where({ department: or({ inactive: true, members: 0 }) })
// becomes
// WHERE department.inactive = true OR department.members = 0

This shouldn't be a breaking change because previously the types limited what constructs could be supplied to each operator so this would technically be an expanding of functionality, but I would need to double check because maybe the code accepted all types to each function anyway which would mean that some javascript code may already be relying on old unsupported behaviour.

This is related to #14 and should probably be implemented together (unless this issue is breaking then #14 should be released soon and this deferred until 5.0).

Using Date results in Neo4jError

Heya!
Using the JavaScript Date primitive results in the following error for me:

{ Neo4jError: Property values can only be of primitive types or arrays thereof

    at captureStacktrace (/Users/berger/workspace/eventzimmer/api/node_modules/neo4j-driver/lib/v1/result.js:200:15)
    at new Result (/Users/berger/workspace/eventzimmer/api/node_modules/neo4j-driver/lib/v1/result.js:73:19)
    at Session._run (/Users/berger/workspace/eventzimmer/api/node_modules/neo4j-driver/lib/v1/session.js:116:14)
    at Session.run (/Users/berger/workspace/eventzimmer/api/node_modules/neo4j-driver/lib/v1/session.js:95:19)
    at n.run (/Users/berger/workspace/eventzimmer/api/node_modules/cypher-query-builder/dist/index.js:1:23282)
    at n.<anonymous> (/Users/berger/workspace/eventzimmer/api/node_modules/cypher-query-builder/dist/index.js:1:8774)
    at e (/Users/berger/workspace/eventzimmer/api/node_modules/cypher-query-builder/dist/index.js:1:7976)
    at Object.next (/Users/berger/workspace/eventzimmer/api/node_modules/cypher-query-builder/dist/index.js:1:7311)
    at /Users/berger/workspace/eventzimmer/api/node_modules/cypher-query-builder/dist/index.js:1:7220
    at new Promise (<anonymous>)
  code: 'Neo.ClientError.Statement.TypeError',
  name: 'Neo4jError' }

My corresponding code looks like:

      let query = new cypher.Query(db)
      query.create([
        cypher.node(event.name, 'Event'),
        cypher.relation('out', ['StartsAt'], { date: event.date }),
        cypher.node(event.location.name, 'Location')
      ])

whereas event.date is a JavaScript date event.date instanceof Date.
The resulting query looks like:

CREATE (commodi:Event)-[:StartsAt $conditions]->(tenetur:Location);

What needs to be done in order to use Date's with this query builder?

OrderBy accepts a dictionary of properties and directions, but dictionary iteration order is not guaranteed

query.orderBy({
  name: 'ASC',
  occupation: 'DESC',
})

In the above example, it is not guaranteed that name will appear first in the final output query.

Arrays should be used instead to control individual property's iteration direction. Eg:

query.orderBy([
  'name',
  [ 'occupation', 'DESC' ]
})

When the individual direction is unspecified, as it is for name above, it should default to ASC or whatever was provided in the dir argument.

Add first method to query

Query and Connection classes should have a first method that returns only the first result from the query or undefined if there are no results.

The type parameter of first should be wrapped in a dictionary, eg:

first<T>(): Dictionary<T>

An in-range update of rollup is breaking the build 🚨

The devDependency rollup was updated from 1.18.0 to 1.19.0.

🚨 View failing branch.

This version is covered by your current version range and after updating it in your project the build failed.

rollup is a devDependency of this project. It might not break your production code or affect downstream projects, but probably breaks your build or test tools, which may prevent deploying or publishing.

Status Details
  • ❌ continuous-integration/travis-ci/push: The Travis CI build failed (Details).

Commits

The new version differs by 6 commits.

  • 9af119d 1.19.0
  • b3f361c Update changelog
  • 456f4d2 Avoid variable from empty module name be empty (#3026)
  • 17eaa43 Use id of last module in chunk as name base for auto-generated chunks (#3025)
  • 871bfa0 Switch to a code-splitting build and update dependencies (#3020)
  • 2443783 Unified file emission api (#2999)

See the full diff

FAQ and help

There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.


Your Greenkeeper Bot 🌴

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.