user2302244
user2302244

Reputation: 935

Opening existing embedded neo4j database

I am trying to use scala over the embedded jave Neo4j api. I am having trouble opening the database for reading on subsequent occasions. The code below should create two nodes and an edge every time it runs, but return all of them at the begining of each run. So, 0 nodes first time, 2 nodes second time, 4 third time etc.

import org.neo4j.tooling.GlobalGraphOperations
import org.neo4j.graphdb.factory.GraphDatabaseFactory
import org.neo4j.graphdb.RelationshipType

object tester extends App{

  val DB_PATH = "data/neo4j"
  object KNOWS extends RelationshipType {
    override def name(): String = "KNOWS"
  }
  val graphDb = new GraphDatabaseFactory().newEmbeddedDatabase(DB_PATH)  //seems to reset the whole directory
  println(graphDb)
  try {
    println("Begin")
    val tx = graphDb.beginTx() // Database operations go here
    println(GlobalGraphOperations.at(graphDb).getAllNodes.iterator)
    val nodes = GlobalGraphOperations.at(graphDb).getAllNodes.iterator
    while (nodes.hasNext()) {
      println(nodes.next())
    }
    nodes.close()
    val relT = GlobalGraphOperations.at(graphDb).getAllRelationships.iterator
    while (relT.hasNext()) {
      println(relT.next())
    }
    println("Success - Begin")
    tx.success()
  }
  try {
    val tx = graphDb.beginTx() // Database operations go here
    val firstNode = graphDb.createNode
    val secondNode = graphDb.createNode
    val relationship = firstNode.createRelationshipTo(secondNode, KNOWS)

    println(firstNode)
    println(secondNode)
    println(relationship)
    println(relationship.getType.name)
    tx.success()
    println("Success")
  }
  println("End")
  try {
    val tx = graphDb.beginTx() // Database operations go here
    println(GlobalGraphOperations.at(graphDb).getAllNodes.iterator)
    val nodes = GlobalGraphOperations.at(graphDb).getAllNodes.iterator
    while (nodes.hasNext()) {
      println(nodes.next())
    }
    nodes.close()
    val relT = GlobalGraphOperations.at(graphDb).getAllRelationships.iterator
    while (relT.hasNext()) {
      println(relT.next())
    }
    println("Success - End")
    tx.success()
  }
  graphDb.shutdown()
}

However, every time it simply seems to give an empty database and then the 2 new nodes. What's going on here?

EmbeddedGraphDatabase [data/neo4j]
Begin
org.neo4j.tooling.GlobalGraphOperations$1$1@74c49a90
Success - Begin
Node[2]
Node[3]
Relationship[1]
KNOWS
Success
End
org.neo4j.tooling.GlobalGraphOperations$1$1@2ec0df08
Node[2]
Node[3]
Relationship[1]
Success - End

Process finished with exit code 0

Upvotes: 0

Views: 309

Answers (2)

Onilton Maciel
Onilton Maciel

Reputation: 3699

This is happening because you are not closing the transaction. You can do this by calling tx.close(). Also I think that instantiating tx inside try is not exactly how it should be. Here is a working version of your program:

import org.neo4j.tooling.GlobalGraphOperations
import org.neo4j.graphdb.factory.GraphDatabaseFactory
import org.neo4j.graphdb.RelationshipType

object tester extends App{

  val DB_PATH = "data/neo4j"
  object KNOWS extends RelationshipType {
    override def name(): String = "KNOWS"
  }
  val graphDb = new GraphDatabaseFactory().newEmbeddedDatabase(DB_PATH)
  println(graphDb)

  val tx1 = graphDb.beginTx() // Database operations go here
  try {
    println("Will list all nodes")
    println("1 - Begin")
    println("GlobalGraphOperations.at(graphDb).getAllNodes.iterator")
    val nodes = GlobalGraphOperations.at(graphDb).getAllNodes.iterator
    while (nodes.hasNext()) {
      println(nodes.next())
    }
    nodes.close()
    val relT = GlobalGraphOperations.at(graphDb).getAllRelationships.iterator
    while (relT.hasNext()) {
      println(relT.next())
    }
    println("1 - Success - Begin")
    tx1.success()
  }
  finally {
    tx1.close()
  }

  val tx2 = graphDb.beginTx() // Database operations go here
  try {
    val firstNode = graphDb.createNode
    val secondNode = graphDb.createNode
    val relationship = firstNode.createRelationshipTo(secondNode, KNOWS)

    println(firstNode)
    println(secondNode)
    println(relationship)
    println(relationship.getType.name)
    tx2.success()
    println("2 - Success")
  }
  finally {
    tx2.close()
  }

  println("2 - End")

  val tx3 = graphDb.beginTx() // Database operations go here
  try {
    println(GlobalGraphOperations.at(graphDb).getAllNodes.iterator)
    val nodes = GlobalGraphOperations.at(graphDb).getAllNodes.iterator
    while (nodes.hasNext()) {
      println(nodes.next())
    }
    nodes.close()
    val relT = GlobalGraphOperations.at(graphDb).getAllRelationships.iterator
    while (relT.hasNext()) {
      println(relT.next())
    }
    println("3 - Success - End")
    tx3.success()
  }
  finally {
    tx3.close()
  }
  graphDb.shutdown()
}

EXTRA

I tried to bring your program closer to the "scala-style". Also, I tried to remove boilerplate and repeated code. To accomplish this I:

  • Used JavaConverters to handle Java collections and Iterables like we handle them in Scala
  • Created a method withTransaction to get automatic resource management for our transaction in scala.

This is the result:

import org.neo4j.tooling.GlobalGraphOperations
import org.neo4j.graphdb.factory.GraphDatabaseFactory
import org.neo4j.graphdb.RelationshipType
import org.neo4j.graphdb.Transaction
import scala.collection.JavaConverters._

object tester extends App{
  val DB_PATH = "data/neo4j"
  object KNOWS extends RelationshipType {
    override def name(): String = "KNOWS"
  }

  def withTransaction (doWithTransaction: Transaction => Unit) { 
    val tempTx = graphDb.beginTx() 

    try {
      doWithTransaction(tempTx)
    }
    finally {
      tempTx.close()
    }
  }

  val graphDb = new GraphDatabaseFactory().newEmbeddedDatabase(DB_PATH)
  println(graphDb)

  withTransaction { tx => 
    println("1 - Begin")
    val nodes = GlobalGraphOperations.at(graphDb).getAllNodes 
    for (node <- nodes.asScala)
      println(node)

    val relTs = GlobalGraphOperations.at(graphDb).getAllRelationships
    for (irelT <- relTs.asScala) 
      println(irelT)

    println("1 - Success - Begin")
    tx.success()
  }


  withTransaction { tx => 
    val firstNode = graphDb.createNode
    val secondNode = graphDb.createNode
    val relationship = firstNode.createRelationshipTo(secondNode, KNOWS)

    println(firstNode)
    println(secondNode)
    println(relationship)
    println(relationship.getType.name)
    tx.success()
    println("2 - Success")
  }

  println("2 - End")

  withTransaction { tx => 
    println(GlobalGraphOperations.at(graphDb).getAllNodes.iterator)

    val nodes = GlobalGraphOperations.at(graphDb).getAllNodes 
    for (node <- nodes.asScala)
      println(node)

    val relTs = GlobalGraphOperations.at(graphDb).getAllRelationships
    for (irelT <- relTs.asScala) 
      println(irelT)

    println("3 - Success - End")
    tx.success()
  }

  graphDb.shutdown()
}

Upvotes: 2

Alessandro Negro
Alessandro Negro

Reputation: 517

the issue is that you are specifying a relative path. May be that everytime you run a clean and build you empty your target directory (or dist, or whatever your ide, development framework use as distribution directory) so the database is empty since it is created from scratch everytime. Try with an absolute path.

Upvotes: 1

Related Questions