An open API service indexing awesome lists of open source software.

https://github.com/outworkers/reactiveneo

[DISCONTINUED] Reactive type-safe Scala driver for Neo4J
https://github.com/outworkers/reactiveneo

Last synced: 12 months ago
JSON representation

[DISCONTINUED] Reactive type-safe Scala driver for Neo4J

Awesome Lists containing this project

README

          

# reactiveneo [![Build Status](https://travis-ci.org/websudos/reactiveneo.svg?branch=develop)](https://travis-ci.org/websudos/reactiveneo) [![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.websudos/reactiveneo_2.10/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.websudos/reactiveneo_2.10)

Reactive type-safe Scala DSL for Neo4j

# Table of contents


  1. Getting it

  2. Graph modelling

  3. Nodes

  4. Relationships

  5. Indexes

  6. Querying

The library enforces strong type checks that imposes some restrictions on query format. Every node and relationship
used in the query needs to be defined and named.
E.g. this kind of query is not supported:
```
MATCH (wallstreet { title:'Wall Street' })<-[r:ACTED_IN]-(actor)
RETURN r
```
Instead you will need to use proper labels for nodes to produce the following query:
```
MATCH (wallstreet:Movie { title:'Wall Street' })<-[r:ACTED_IN]-(actor:Actor)
RETURN r
```

# Getting it

```scala
libraryDependencies ++= Seq(
"com.websudos" %% "reactiveneo-dsl" % "0.3.0",
"com.websudos" %% "reactiveneo-testing" % "0.3.0"
)
```

# Graph modelling
Back to top

## Nodes
Back to top

Domain model class
```
case class Person(name: String, age: Int)
```

Reactiveneo node definition
```
import com.websudos.reactiveneo.dsl._

class PersonNode extends Node[PersonNode, Person] {

object name extends StringAttribute with Index

object age extends IntegerAttribute

def fromNode(data: QueryRecord): Person = {
Person(name[String](data), age[Int](data))
}

}
```

## Relationships
Back to top

Reactiveneo relationship definition
```
import com.websudos.reactiveneo.dsl._

class PersonRelation extends Relationship[PersonRelation, Person] {

object name extends StringAttribute with Index

object age extends IntegerAttribute

def fromNode(data: QueryRecord): Person = {
Person(name[String](data), age[Int](data))
}

}
```

## Indexes
Back to top

# Querying
Back to top

## Connection

Prerequisite to making Neo4j requests is REST endpoint definition. This is achived using RestConnection class.

```
scala> implicit val service = RestConnection("localhost", 7474)
service: RestConnection
```

## Making requests

In this example all nodes of Person type are returned.
```
scala> val personNodes = Person().returns(case p ~~ _ => p).execute
personNodes: Future[Seq[Person]]
```

The strange construct in the returns function is execution of extractor in the pattern. Pattern defines set of objects
that participate in the query. The objects are nodes and relationships.

You can also query for specific attributes of a node.
```
scala> val personNames = Person().returns(case p ~~ _ => p.name).execute
personNames: Future[Seq[String]]
```

A query that involves attributes matching.
```
scala> val personNodes = Person(_.name := "Tom").returns(case p ~~ _ => p).execute
personNodes: Future[Seq[Person]]
```

Query for a person that has a relationship to another person
```
scala> val personNodes = (Person() :->: Person())
.returns(case p1 ~~ _ => p).execute
personNodes: Future[Seq[Person]]
```

Query for a person that has a relationship to another person with given name
```
scala> val personNodes = (Person() :->: Person(_.name := "James"))
.returns(case p ~~ _ => p).execute
personNodes: Future[Seq[Person]]
```

Query for a person that has a relationship to another person
```
scala> val personNodes = (Person() :<-: WorkRelationship() :->: Person())
.returns(case p1 ~~ r ~~ p2 ~~ _ => p1).execute
personNodes: Future[Seq[Person]]
```

Query for a person that has a relationship to another person with given name
```
scala> val personNodes = (Person() :-: WorkRelationship(_.company := "ABC") :->: Person(_.name := "John"))
.returns(case p1 ~~ _ => p1).execute
personNodes: Future[Seq[Person]]
```

## An arbitrary Cypher query
Cypher is a rich language and whenever you need to use it directly escaping the abstraction layer it's still possible
with ReactiveNeo. Use the same REST connection object with an arbitrary Cypher query.
```
scala> val query = "MATCH (n:Person) RETURN n"
query: String
implicit val parser: Reads[Person] = ((__ \ "name").read[String] and (__ \ "age").read[Int])(Person)

parser: Reads[Person]
val result = service.makeRequest[Person](query).execute
result: Future[Seq[Person]]
```