Issue 1:
@vlg: 'OK so there is an issue with key-value automatic indices (code bellow) upon node removal. The scenario tested here is the following:

Assume that we index a property named 'ID', and that we want to use it to manage unicity of nodes. We create a database, and init indexing of this property, then we do the following:

addNode('N1)

deleteNode('N1)

graph.shutdown()

graph.openAgain()

addNode('N1')

addNode('N2')

getNodeFromIndex('ID', 'N1)

The issue is that nothing is retrieved by the last instruction while N1 should be retrieved. Additional observations:

(1) If we add N2 BEFORE N1, results are OK

(1) If we do not remove N1, results are OK

(2) If we don't close and reopen the database, results are OK

(3) If we drop the reference node at the database creation, results are OK

CODE:

import java.util.logging.Level;
import java.util.logging.Logger;
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.NotFoundException;
import org.neo4j.graphdb.Transaction;
import org.neo4j.graphdb.index.IndexHits;
import org.neo4j.kernel.EmbeddedGraphDatabase;

public class Neo4jKeyIndexIssues
{
public static final String DBPATH = "NeoTest" ;
public static final String INDEXED = "ID" ;
public static final String N1 = "Node1" ;
public static final String N2 = "Node2" ;

public static void main(String[] args)
throws Exception {

Node node1, node2 ;

GraphDatabaseService g = new EmbeddedGraphDatabase(DBPATH);
g.index().getNodeAutoIndexer().setEnabled(true);
g.index().getNodeAutoIndexer().startAutoIndexingProperty(INDEXED);

// dropNeoReferenceNode(g);

System.out.println("(1)");
node1 = addNode(g, N1);

IndexHits<Node> hits = g.index().getNodeAutoIndexer().getAutoIndex().get(INDEXED, N1);
System.out.println("1) Query Hits for '"+N1+"': " + hits.size()+" "+hits.hasNext());
Node hit = hits.getSingle();
System.out.println("1) Hit for '"+N1+"': " + hit.getProperty(INDEXED));

// Remove the nodes
Transaction tx = g.beginTx();
System.out.println("Removing node 1 "+N1);
node1.delete();
tx.success(); tx.finish();

// Reopen database
System.out.println("-Shutting down and reopening the database-");
g.shutdown();
g = new EmbeddedGraphDatabase(DBPATH);
g.index().getNodeAutoIndexer().setEnabled(true);
g.index().getNodeAutoIndexer().startAutoIndexingProperty(INDEXED);

// OK, add new nodes again
System.out.println("\n(2)");
node1 = addNode(g, N1);
node2 = addNode(g, N2);

hits = g.index().getNodeAutoIndexer().getAutoIndex().get(INDEXED, N1);
System.out.println("2) Query Hits for 'N1': "+hits.size()+" "+hits.hasNext());

// Something should be found
node1 = hits.getSingle();
if(node1 == null) {
System.out.println("2) ERROR: nothing found ID='"+N1+"'");
}
else {
System.out.println("2) Hit for 'N1': " + node1+" ID="+node1.getProperty("ID"));
}

// Something should be found too
hits = g.index().getNodeAutoIndexer().getAutoIndex().get(INDEXED, N2);
System.out.println("2) Query Hits for 'N2': "+hits.size()+" "+hits.hasNext());

// Nothing was found
node2 = hits.getSingle();
if(node2 == null) {
System.out.println("2) ERROR: nothing found ID='"+N2+"'");
}
else {
System.out.println("2) Hit for 'N2': " + node2+" ID="+node2.getProperty("ID"));
}

g.shutdown();
}

/**
* Add a node to a database, only if a node with the same identifier does not
* exist yet.
*/
private static Node addNode(GraphDatabaseService g, String id)
throws Exception {
System.out.println("Adding node "+id);

Transaction tx = g.beginTx();

Node node = null ;
try {
IndexHits<Node> hits =
g.index().getNodeAutoIndexer().getAutoIndex().get("ID", id);

System.out.println(" Existing nodes in index: "+hits.size()+" "+hits.hasNext());
if(hits.size() > 0 && hits.hasNext()) {
System.out.print(" Duplicate: "+id);

node = hits.getSingle();
System.out.println(" --> "+node);
return node;
}

node = g.createNode();
node.setProperty("ID", id);

tx.success();
}
catch(Exception e) {
Logger.getLogger("App").log(Level.FINE,
"Could not add node node "+id, e);
throw e ;
}
finally {
tx.finish();
}

System.out.println(" Node added: "+node);

return node;
}

/**
* Drop the refernce node from a database
*/
private static void dropNeoReferenceNode(GraphDatabaseService neoGraph) {
Transaction t = neoGraph.beginTx();
try {
Node node = neoGraph.getReferenceNode();
if (node != null) {
node.delete();
}
t.success();
}
catch (NotFoundException e) {
Logger.getLogger("App").log(Level.FINE,
"Could not drop reference node!", e);
t.failure();
}
finally {
t.finish();
}
}
}

'

Issue 2:
Currently there doesn't seem to be a way to configure the isolation level for a transaction (especially SERIALIZABLE) when using the REST API.

I'm trying to create friendly id's for child objects using the following:

CREATE (o:Foo {name: 'parent', nextChildId: 1})

MATCH (o:Foo)
WHERE o.name = 'parent'
CREATE (o)-[:HAS]->(c:Child {name: 'child1', friendlyId: o.nextChildId})
SET o.nextChildId = o.nextChildId + 1

// if this call comes in before the previous SET, we have a problem
MATCH (o:Foo)
WHERE o.name = 'parent'
CREATE (o)-[:HAS]->(c:Child {name: 'child2', friendlyId: o.nextChildId})
SET o.nextChildId = o.nextChildId + 1

But without being able to take a lock on the parent node there isn't a way to prevent two child nodes from getting assigned the same friendly id.