Neo4j with Scala : User Defined Procedure and APOC

Reading Time: 5 minutes

In the last blog Getting Started Neo4j with Scala : An Introduction which got the overwhelming response from Neo4j and Dzone. We discussed about how to use Neo4j with Scala. For recap Blog and the Code. Now we are going to take one step ahead .

As we know that in the Relational Database, Procedure provide advantages of better performance, scalability, productivity, ease of use and security.

In the Neo4j we also used APOC and User Defined Procedure which provide same advantages which we get in the Relational Database.

User Defined Function

We used user defined procedure in the Relational Database which we store in the database and call from there whenever needed. In Neo4j we also do the same thing. Here we create procedure method with the @Procedure annotation.

When we annotated with @Procedure, it takes any Cypher Type as parameters and returns Stream of Data Transfer Objects (DTO).

When procedure write to database that time we also use @PerformWrites annotation.

we should use procedure for the common tasks or for those task which you use more frequently, because for all the purpose we can not create procedure.

When we complete creation of procedure than we have to make its jar and put that jar into $Neo4j_Home/plugins/ and restart the Neo4j. While making the jar please be careful that all dependencies also become the part of jar or dependencies will not be found when procedure is loaded.

After putting jar and restarting server run this cypher to check your listed procedure.

CALL dbms.procedures();

You can also check the log: $Neo4j_Home/logs/debug.log the listed procedure in logs.

You can also check the log: $Neo4j_Home/logs/neo4j.log if server is not starting. It will provide you a clear picture of mistakes.

When we try to create procedure than we have to use Java 1.8. Any version below this, will not help to create procedure. There is a reason for that, Java introduce ‘ Stream ‘ and all the final result we return in Stream in procedure. We also use Scala 2.12.0-M5 for using Java lambda in Scala.

Another thing when we use Scala for creating procedure than we have to use Java also file because only static fields and @Context-annotated fields are allowed in Procedure classes. we also define that class which contains result and send as an object in Stream we define here, it contains public variable because when we define public variable in Scala, Neo4j compiler unable to access it.

Now we start creating file in Java and define there all the context variable:

@Context public GraphDatabaseService db;
@Context public Log log;

 

Now we define procedure as a method in Scala file, which will return Stream<Output>. Here we are trying to create a procedure which will search ‘NodeId’ with the help of “Label” and “Query” and will return it as a Stream[SearchHit] where SearchHit is a static class which we define in Java file and it is result. Here is a code :

@Procedure(&quot;example.search&quot;)
@PerformsWrites
def search(@Name(&quot;label&quot;) label: String, @Name(&quot;query&quot;) query: String): Stream[SearchHit] = {
  val index: String = indexName(label)
  if (!db.index.existsForNodes(index)) {
    log.debug(&quot;Skipping index query since index does not exist: `%s`&quot;, index)
    Stream.empty
  }
  val nodes: Stream[Node] = db.index.forNodes(index).query(query).stream

  val javaFunction: java.util.function.Function[Node, SearchHit] = (node: Node) =&amp;gt; new SearchHit(node)
  nodes.map {
    javaFunction
  }
}

And in the Java file we create result class like:

public static class SearchHit {
    public long nodeId;
    public SearchHit(Node node) {
        this.nodeId = node.getId();
    }
}

Now we create jar file for the procedure and put it in $Neo4j_Home/plugins/ and restart the Neo4j Server.

For checking that procedure is listed there or not, we can use this cypher :

CALL dbms.procedures() YIELD name
RETURN head(split(name,&quot;.&quot;)) as package, count(*), collect(name) as procedures;

Here we find :

udf

Now as we can see, here is a new package name “example” which contains “example.search”.

Now we can call this procedure with its parameter :

CALL example.search('User', 'name:Brook*')

callproc.png

Awesome Procedure on Cypher(APOC)

What is APOC?

When we listen APOC, most of the people start thinking of “APOC” which is a character in ‘Matrix’ movie and those are right. It comes from there and first bundle of ‘A Package Of Component’ for Neo4j.

APOC is stands for ‘Awesome Procedure On Cypher‘. APOC is a library of procedure for the various areas. It is introduce with the Neo4j 3.0 . It is containing currently 206 libraries and its still growing. We can see this with using :

CALL dbms.procedures() YIELD name
RETURN head(split(name,&quot;.&quot;)) as package, count(*), collect(name) as procedures;

 

dbms.procedure.count.jpg

List of Areas from where it contains procedures are:

  • Graph Algorithm
  • Metadata
  • Manual indexes and relationship indexes
  • Full text search
  • Integration with other databases like MongoDB, ElasticSearch, Cassandra and relational databases
  • Path expansion
  • Import and export
  • date and time function
  • Loading of XML and JSON from APIs and files
  • String and text function
  • Concurrent and batched Cypher Execution
  • spatial Function and Lock
  • Collection and map utilities

These are the major areas for which it contains procedure and still it is growing.

How we can use APOC with latest release?

We have two ways to use the APOC with our Neo4j.

First Way :

  • Download binary jar from the latest release [Hit Here]
  • Put that into your $Neo4j_Home/plugins/ folder
  • Restart your Neo4j.

Second Way :

  • Clone neo4j-apoc-procedure from Hit Here.
  • Go to the folder with ‘cd neo4j-apoc-procedures’.
  • Now create a jar with the help of command ‘mvn clean compile install’.
  • Now copy your jar file from target to $Neo4j_Home/plugins/ folder.[cp target/apoc-1.0.0-SNAPSHOT.jar $Neo4j_Home/plugins/]
  • Restart your Neo4j.

Now configure your plugins in ‘conf/neo4j.conf’ with “dbms.plugin.directory=plugin’s path”, if you want to use it in embedded mode.

Now after restarting your Neo4j, you can check procedure list. We used ‘ CALL ‘ for calling the procedure along with procedure_name.

CALL dbms.procedures();

dbms.procedure.jpg

Now we can call help for the help function which is built into library.

CALL apoc.help("apoc")

apoc-help.jpg

We can use APOC for the various statement directly in the Cypher. Here, you can find full usage of APOC Library.

This is a start for user defined procedure in Neo4j with Scala.

I hope it will help for creating procedure with Scala. Please, provide your suggestion for make it more fine.

You can get the above working example for Scala from the github repo, checkout : GitHub

Thanks.

Reference:

  1. Neo4j Procedure
  2. Neo4j Procedure Java Template

KNOLDUS-advt-sticker

Written by 

Anurag is the Sr. Software Consultant @ Knoldus Software LLP. In his 3 years of experience, he has become the developer with proven experience in architecting and developing web applications.

9 thoughts on “Neo4j with Scala : User Defined Procedure and APOC6 min read

  1. creating java files in a scala project is considered scala now? I guess every java-api is now considered a scala app now!

Comments are closed.

Discover more from Knoldus Blogs

Subscribe now to keep reading and get access to the full archive.

Continue reading