1 | # Neo4j Driver for Javascript
|
2 |
|
3 |
|
4 | A database driver for Neo4j 3.0.0+.
|
5 |
|
6 | Resources to get you started:
|
7 |
|
8 | * [Detailed docs](http://neo4j.com/docs/api/javascript-driver/current/).
|
9 | * [Sample small project using the driver](https://github.com/neo4j-examples/movies-javascript-bolt)
|
10 | * [Sample application using the driver](https://github.com/neo4j-examples/neo4j-movies-template)
|
11 | * [Neo4j Manual](https://neo4j.com/docs/)
|
12 | * [Neo4j Refcard](https://neo4j.com/docs/cypher-refcard/current/)
|
13 |
|
14 | ## Include module in Node.js application
|
15 |
|
16 | Stable channel:
|
17 | ```shell
|
18 | npm install neo4j-driver
|
19 | // or
|
20 | bower install neo4j-driver
|
21 | ```
|
22 |
|
23 | Pre-release channel:
|
24 | ```shell
|
25 | npm install neo4j-driver@next
|
26 | ```
|
27 |
|
28 | Please note that `@next` only points to pre-releases that are not suitable for production use.
|
29 | To get the latest stable release omit `@next` part altogether or use `@latest` instead.
|
30 |
|
31 | ```javascript
|
32 | var neo4j = require('neo4j-driver').v1;
|
33 | ```
|
34 | Driver instance should be closed when Node.js application exits:
|
35 |
|
36 | ```javascript
|
37 | driver.close();
|
38 | ```
|
39 |
|
40 | otherwise application shutdown might hang or it might exit with a non-zero exit code.
|
41 |
|
42 | ## Include in web browser
|
43 |
|
44 | We build a special browser version of the driver, which supports connecting to Neo4j over WebSockets.
|
45 |
|
46 | ```html
|
47 | <script src="lib/browser/neo4j-web.min.js"></script>
|
48 | ```
|
49 |
|
50 | This will make a global `neo4j` object available, where you can access the `v1` API at `neo4j.v1`:
|
51 |
|
52 | ```javascript
|
53 | var driver = neo4j.driver("bolt://localhost", neo4j.auth.basic("neo4j", "neo4j"));
|
54 | ```
|
55 |
|
56 | It is not required to explicitly close the driver on a web page. Web browser should gracefully close all open
|
57 | WebSockets when the page is unloaded. However, driver instance should be explicitly closed when it's lifetime
|
58 | is not the same as the lifetime of the web page:
|
59 |
|
60 | ```javascript
|
61 | driver.close();
|
62 | ```
|
63 |
|
64 | ## Usage examples
|
65 |
|
66 | ```javascript
|
67 |
|
68 | // Create a driver instance, for the user neo4j with password neo4j.
|
69 | // It should be enough to have a single driver per database per application.
|
70 | var driver = neo4j.driver("bolt://localhost", neo4j.auth.basic("neo4j", "neo4j"));
|
71 |
|
72 | // Register a callback to know if driver creation was successful:
|
73 | driver.onCompleted = function() {
|
74 | // proceed with using the driver, it was successfully instantiated
|
75 | };
|
76 |
|
77 | // Register a callback to know if driver creation failed.
|
78 | // This could happen due to wrong credentials or database unavailability:
|
79 | driver.onError = function(error) {
|
80 | console.log('Driver instantiation failed', error);
|
81 | };
|
82 |
|
83 | // Create a session to run Cypher statements in.
|
84 | // Note: Always make sure to close sessions when you are done using them!
|
85 | var session = driver.session();
|
86 |
|
87 | // Run a Cypher statement, reading the result in a streaming manner as records arrive:
|
88 | session
|
89 | .run("MERGE (alice:Person {name : {nameParam} }) RETURN alice.name", { nameParam:'Alice' })
|
90 | .subscribe({
|
91 | onNext: function(record) {
|
92 | console.log(record._fields);
|
93 | },
|
94 | onCompleted: function() {
|
95 | // Completed!
|
96 | session.close();
|
97 | },
|
98 | onError: function(error) {
|
99 | console.log(error);
|
100 | }
|
101 | });
|
102 |
|
103 | // or
|
104 | // the Promise way, where the complete result is collected before we act on it:
|
105 | session
|
106 | .run("MERGE (james:Person {name : {nameParam} }) RETURN james.name", { nameParam:'James' })
|
107 | .then(function(result){
|
108 | result.records.forEach(function(record) {
|
109 | console.log(record._fields);
|
110 | });
|
111 | // Completed!
|
112 | session.close();
|
113 | })
|
114 | .catch(function(error) {
|
115 | console.log(error);
|
116 | });
|
117 |
|
118 | //run statement in a transaction
|
119 | var tx = session.beginTransaction();
|
120 | tx.run("MERGE (bob:Person {name : {nameParam} }) RETURN bob.name", { nameParam:'Bob' })
|
121 | .subscribe({
|
122 | onNext: function(record) {
|
123 | console.log(record._fields);
|
124 | },
|
125 | onCompleted: function() {
|
126 | // Completed!
|
127 | session.close();
|
128 | },
|
129 | onError: function(error) {
|
130 | console.log(error);
|
131 | }
|
132 | });
|
133 |
|
134 | //decide if the transaction should be committed or rolled back
|
135 | var success = false;
|
136 |
|
137 | if (success) {
|
138 | tx.commit()
|
139 | .subscribe({
|
140 | onCompleted: function() {
|
141 | // Completed!
|
142 | },
|
143 | onError: function(error) {
|
144 | console.log(error);
|
145 | }
|
146 | });
|
147 | } else {
|
148 | //transaction is rolled black and nothing is created in the database
|
149 | console.log('rolled back');
|
150 | tx.rollback();
|
151 | }
|
152 |
|
153 | // Close the driver when application exits
|
154 | driver.close();
|
155 | ```
|
156 |
|
157 | Subscriber API allows following combinations of `onNext`, `onCompleted` and `onError` callback invocations:
|
158 | * zero or more `onNext` followed by `onCompleted` when operation was successful. `onError` will not be invoked
|
159 | in this case
|
160 | * zero or more `onNext` followed by `onError` when operation failed. Callback `onError` might be invoked after
|
161 | couple `onNext` invocations because records are streamed lazily by the database. `onCompleted` will not be invoked
|
162 | in this case
|
163 |
|
164 | ## Building
|
165 |
|
166 | npm install
|
167 | npm build
|
168 |
|
169 | This produces browser-compatible standalone files under `lib/browser` and a Node.js module version under `lib/`.
|
170 | See files under `examples/` on how to use.
|
171 |
|
172 | ## Testing
|
173 |
|
174 | ./runTests.sh
|
175 |
|
176 | This runs the test suite against a fresh download of Neo4j.
|
177 | Or `npm test` if you already have a running version of a compatible Neo4j server.
|
178 |
|
179 | For development, you can have the build tool rerun the tests each time you change
|
180 | the source code:
|
181 |
|
182 | gulp watch-n-test
|
183 |
|
184 | ### Testing on windows
|
185 | Running tests on windows requires PhantomJS installed and its bin folder added in windows system variable `Path`.
|
186 | To run the same test suite, run `.\runTest.ps1` instead in powershell with admin right.
|
187 | The admin right is required to start/stop Neo4j properly as a system service.
|
188 | While there is no need to grab admin right if you are running tests against an existing Neo4j server using `npm test`.
|
189 |
|
190 | ## A note on numbers and the Integer type
|
191 | The Neo4j type system includes 64-bit integer values.
|
192 | However, Javascript can only safely represent integers between `-(2`<sup>`53`</sup>` - 1)` and `(2`<sup>`53`</sup>` - 1)`.
|
193 | In order to support the full Neo4j type system, the driver will not automatically convert to javascript integers.
|
194 | Any time the driver receives an integer value from Neo4j, it will be represented with an internal integer type by the driver.
|
195 |
|
196 | ### Write integers
|
197 | Number written directly e.g. `session.run("CREATE (n:Node {age: {age}})", {age: 22})` will be of type `Float` in Neo4j.
|
198 | To write the `age` as an integer the `neo4j.int` method should be used:
|
199 |
|
200 | ```javascript
|
201 | var neo4j = require('neo4j-driver').v1;
|
202 |
|
203 | session.run("CREATE (n {age: {myIntParam}})", {myIntParam: neo4j.int(22)});
|
204 | ```
|
205 |
|
206 | To write integers larger than can be represented as JavaScript numbers, use a string argument to `neo4j.int`:
|
207 |
|
208 | ```javascript
|
209 | session.run("CREATE (n {age: {myIntParam}})", {myIntParam: neo4j.int("9223372036854775807")});
|
210 | ```
|
211 |
|
212 | ### Read integers
|
213 | Since Integers can be larger than can be represented as JavaScript numbers, it is only safe to convert to JavaScript numbers if you know that they will not exceed `(2`<sup>`53`</sup>` - 1)` in size.
|
214 | In order to facilitate working with integers the driver include `neo4j.isInt`, `neo4j.integer.inSafeRange`, `neo4j.integer.toNumber`, and `neo4j.integer.toString`.
|
215 |
|
216 | ```javascript
|
217 | var aSmallInteger = neo4j.int(123);
|
218 | if (neo4j.integer.inSafeRange(aSmallInteger)) {
|
219 | var aNumber = aSmallInteger.toNumber();
|
220 | }
|
221 | ```
|
222 |
|
223 | If you will be handling integers larger than that, you can should convert them to strings:
|
224 |
|
225 | ```javascript
|
226 | var aLargerInteger = neo4j.int("9223372036854775807");
|
227 | if (!neo4j.integer.inSafeRange(aSmallInteger)) {
|
228 | var integerAsString = aLargerInteger.toString();
|
229 | }
|
230 | ```
|
231 |
|