Neo4j Tutorial

Third Party Integrations

Introduction

This guide will help you integrate KeyLines with Neo4j, one of many popular databases you can use with KeyLines.

This tutorial uses the Neo4j Javascript driver to connect a simple KeyLines application to a Neo4j database. The driver uses the Bolt protocol to connect to the database, and has three advantages over using a REST API/HTTP protocol:

  • Speed – binary encoding means less data gets sent over the wire, and access is faster.
  • Performance – using Websockets, high volumes of queries are executed more quickly, giving higher throughput and lower latency.
  • Security – Bolt has TLS security built and enabled by default in to protect the data connection.

For more information on how you can load your formatted data into KeyLines, see also Loading Data.

Step 1: Setting up the environment

To connect our KeyLines application to our Neo4j database locally, make sure you have the latest version of Node.js installed. To check your version, you can run node -v in the console.

First, download our Neo4j Demo source files from the link below:

Download Neo4j Demo

This will download the demo as a neo4j.zip archive. Unzip it into a neo4j directory.

Next, download the KeyLines package from the link below:

Download KeyLines

This will download KeyLines as a keylines.tgz file. Place this file in the neo4j directory.

In the terminal from the neo4j directory, add KeyLines as a package dependency:

npm add file:./your_downloaded_file_name.tgz

Finally, download and install the Neo4j Desktop application from the Neo4j website. Once you've installed it, continue to Step 2 of this tutorial.

Step 2: Creating a Neo4j database

Open the Neo4j Desktop application.

The application opens in an Example Project. Add a new database by clicking the Add button and selecting 'Local DBMS':

Neo4j desktop Projects window

Set the database name to 'Movies' and the password to 'keylines'. We will need these details later.

Local DBMS creation dialog

Hover the mouse over the Movies database to display the context menu.

Click the (...) button, locate the Open folder dropdown and select 'Import':

Path to import in the created database

This opened your local directory to the imports folder of your Neo4j Desktop application.

Copy the two csv source files in ../neo4j-data into this directory. Do not change the file names.

Back on the main app window, click the (...) button again and select 'Terminal' to open a new terminal tab. In the terminal, import our CSV files into a new database:

bin/neo4j-admin database import full --nodes "import/vertex-data.csv" --relationships "import/edge-data.csv" --trim-strings=true movies

We should also update our settings to specify which database to mount. Click the (...) button and select 'Settings'.

In the Settings window, find the Initial DBMS Settings section to set Movies as our default database:

dbms.default_database=Movies

Enter the database and click Apply. Your Settings window should now look like this:

Neo4j desktop Settings window

Now click the Start button to start the database.

We can check that our database was loaded correctly by opening the browser and running a query.

In the left-side vertical navigation bar, locate the Graph Apps section thumbnail Graph Apps section and select Neo4j Browser.

Movies should be the active database in use (with the name displayed in the query window). In the query window, run the following query:

// Get some data
MATCH (n1)-[r]->(n2) RETURN r, n1, n2 LIMIT 25

Our Neo4j database is now live and ready for us to query.

Step 3: Connecting KeyLines to the database

Returning to our demo source files, in ../neo4j/neo4j-router.js, update the config object with the password that we set in Step 2 and save your changes.

const configs = {
  // The port here should match your server's connection status
  boltPath: 'bolt://localhost/',
  // The username for the database. The default username is neo4j.
  username: 'neo4j',
  // The password for the database. This is password we entered above in Step 2.
  password: 'keylines',
};

Now in our neo4j demo source file directory, install the required node modules using npm and start the application:

npm install && npm start

If you navigate to localhost:8080 you should now see the KeyLines app has loaded the data from the local server into the chart:

Neo4j KeyLines demo screenshot

You have now successfully retrieved data from a KeyLines app and loaded it into a chart.

Understanding the application architecture

Our application is performing three important steps to visualize data from Neo4j in a KeyLines chart.

  • Send a query to and retrieve data from a Neo4j database,
  • Convert this response JSON data into the required KeyLines format,
  • Display it in our KeyLines visualisation.

Let's go through each step in detail.

Querying the Neo4J database

After running yarn start or npm start, we create a new local endpoint ('/neo4jdb'), which will use the Neo4j JavaScript driver to make queries to our neo4j database. The install has already loaded the module into our node environment.

Our new endpoint receives two arguments, the first is either 'Movie' or 'Actor' and the second is the movie title or actor name. These arguments are inserted into our prepared Cypher queries, and sent to the Neo4J database, which will return a JSON response using the Bolt protocol.

In neo4j-router.js, we import the driver, and then set it up using our authentication from the config object.

const neo4j = require('neo4j-driver');
// Set up the Neo4j JavaScript driver
const driver = neo4j.driver(
    configs.boltPath,
    neo4j.auth.basic(configs.username, configs.password),
    { disableLosslessIntegers: true },
  );

Once our driver is setup, we are able to create sessions in which to run queries.

Let's take a closer look at the setupEndpoint() function:

function setupEndpoint(app) {
    // We add a new endpoint onto our existing express app that accepts a query
    app.get('/neo4jdb/:queryType',
      async (req, res) => {
        // Create a new session in which we can query the database
        const session = await driver.session();
        // Once our query has been completed, we close our session
        res.on('finish', () => session.close());
        try {
          // We send our query using the run method, using our Cypher query templates
          const response = await session.run(queryTemplates[req.params.queryType],
            { nameParam: req.query.name });
          // We would also like to return our query as part of the response
          // Here we simply update the query with the arguments that were used
          let statement = response.summary.query.text.replace('$nameParam',
            `"${response.summary.query.parameters.nameParam}"`);
          statement = statement.replace('RETURN', '\nRETURN');
          console.info(`Neo4j statement: ${statement}`);
          // We return to the client the response as well as the query we used.
          res.send({ rawItems: response.records, statement });
        } catch (err) {
          console.error('Unable to connect to Neo4j', configs);
          res.send({ error: 'Unable to connect to Neo4j' });
        }
      });
  }

Our returned JSON response will be as follows:

{
  "records": [
    {
        "keys": [
            "actorName",
            "movieTitle",
            "actorId",
            "movieId",
            "degree"
        ],
        "length": 5,
        "_fields": [
            "Marc Aden",
            "The Matrix",
            108,
            90,
            1
        ],
        "_fieldLookup": {
            "actorName": 0,
            "movieTitle": 1,
            "actorId": 2,
            "movieId": 3,
            "degree": 4
        }
    },
    ...
  ]
}

Converting to KeyLines format

The neo4j-db.js file iterates through returned JSON data and converts it into the correct KeyLines format.

As an example, when we receive the above JSON back from the server, the toKeyLinesFormat() function parses our initial query response. It converts the 'Marc Aden' response to 2 objects in an array; one link and one node:

items = [
  {"id":"108", "type":"node", "t":"Marc Aden", "d": {"degree":1, "type":"actor", "expanded":true}, "tc":false},
  {"id":"108-90", "type":"link", "id1":"108", "id2":"90", "c":"#C4C4C4", "w":3}
]

The items array is now ready to be loaded into our chart using chart.expand().

Terms of use

These terms do not alter or supersede any existing agreements between you (or your employer) and us.

By accessing or using any Content you agree to be bound by these Terms of Use. Please review these terms carefully before using the website.

The contents of this website, including but not limited to any text, code samples, API references, schemas, interactive tools, and other materials (collectively, the 'Content'), are made available for informational and internal evaluation purposes only. All intellectual property rights in the Content are reserved. No licence is granted to use the Content for any commercial purpose, or to copy, distribute, modify, reverse-engineer, or incorporate any part of the Content into any product or service, without our prior written consent.

This Content is provided “as is” and “as available,” without any representations, warranties, or guarantees of any kind, whether express or implied, including but not limited to implied warranties of merchantability, fitness for a particular purpose, non-infringement, or accuracy. To the fullest extent permitted by applicable law, we expressly exclude and disclaim all implied warranties, conditions, and other terms that might otherwise be implied.

We disclaim all liability for any loss or damage, whether direct, indirect, incidental, consequential, or otherwise, arising from any reliance placed on the Content or from your use of it, to the fullest extent permitted by applicable law. By continuing to access or use the Content, you acknowledge and agree to these terms.