2

I'm successfully using the Neo4J Java API (currently version 2.2.1) to do simple queries like this:

Label label = DynamicLabel.label("User");
ResourceIterator<Node> providers = graphDb.findNodes(
        label, "username", "player1"));

But is there a way to allow something other than a simple match (String in my case) for the values? Can I do REGEX, or provide a list of possible values that the key could match on for string comparisons? If so, are there any examples out there?

I've dug around the docs and my favorite search engines and can't seem to find anything other than a straight string match (such as this: http://neo4j.com/docs/2.2.1/tutorials-java-embedded-new-index.html).

Jeff G.
  • 23
  • 4

2 Answers2

2

Write your own code.. Cypher is slow. See the difference for only 4 nodes with query label ("USER"). full db has only 8 nodes!

package com.mycompany.neo4j_0;

import java.util.Iterator;
import java.util.Map;
import org.neo4j.graphdb.DynamicLabel;
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.ResourceIterator;
import org.neo4j.graphdb.Result;
import org.neo4j.graphdb.Transaction;
import org.neo4j.graphdb.factory.GraphDatabaseFactory;

public class NewMain {

private static void registerShutdownHook(final GraphDatabaseService graphDb) {
    // Registers a shutdown hook for the Neo4j instance so that it
    // shuts down nicely when the VM exits (even if you "Ctrl-C" the
    // running application).
    Runtime.getRuntime().addShutdownHook(new Thread() {
        @Override
        public void run() {
            graphDb.shutdown();
        }
    });
}

public static void PrintPropertyKeysAndValues(Node t_node) {
    Map<String, Object> propertiesMap = t_node.getAllProperties();
    propertiesMap.entrySet().stream().forEach((entry) -> {
        System.out.printf("Key : %s and Value: %s %n", entry.getKey(), entry.getValue());
    });
}

public static void GetNodesWithLabel_and_PropertyKey(GraphDatabaseService graphDB, String label, String PropertyKey) {
    ResourceIterator<Node> nodes = graphDB.findNodes(DynamicLabel.label(label));
    int flag = 0;
    while (nodes.hasNext()) {
        Node t_node = nodes.next();
        Map<String, Object> propertiesMap = t_node.getAllProperties();
        for (Map.Entry<String, Object> entry : propertiesMap.entrySet()) {
            //System.out.printf("Key : %s and Value: %s %n", entry.getKey(), entry.getValue());
            if (entry.getKey().equals(PropertyKey)) {
                PrintPropertyKeysAndValues(t_node);
                flag = 1;
            }
        }
    }
    if (flag == 0) {
        System.out.println("No Nodes found with this property");
    }
}

public static void GetNodesWithLabel_and_PropertyKeyCypher(GraphDatabaseService graphDB, String label, String PropertyKey) {
    String query = "MATCH (n:" + label + ") where n." + PropertyKey + " =~ '.*' RETURN n;";
    Result result = graphDB.execute(query);
    Iterator<Node> nodes = result.columnAs("n");

    int flag = 0;
    while (nodes.hasNext()) {
        Node t_node = (Node) nodes.next();
        Map<String, Object> propertiesMap = t_node.getAllProperties();
        for (Map.Entry<String, Object> entry : propertiesMap.entrySet()) {
            //System.out.printf("Key : %s and Value: %s %n", entry.getKey(), entry.getValue());
            if (entry.getKey().equals(PropertyKey)) {
                PrintPropertyKeysAndValues(t_node);
                flag = 1;
            }
        }
    }
    if (flag == 0) {
        System.out.println("No Nodes found with this property");
    }
}

public static void main(String[] args) {

// Find nodes with Specified Label and with a Specified PropertyKey.
    long start_time = 0, end_time = 0, difference1 = 0, difference2 = 0;
    String label="USER";
    String PropertyKey="name";


    GraphDatabaseService graphDB;

    graphDB = new GraphDatabaseFactory().newEmbeddedDatabase("Z:\\neo4j-community-2.3.2\\data\\test\\graph.db");
    registerShutdownHook(graphDB);

    try (Transaction tx = graphDB.beginTx()) {

        System.out.println("==================JavaApi==================");
        start_time = System.nanoTime();
        GetNodesWithLabel_and_PropertyKey(graphDB, label, PropertyKey);
        end_time = System.nanoTime();
        difference1 = end_time - start_time;
        System.out.println("java time: " + difference1);

        System.out.println("==================Cypher==================");
        start_time = System.nanoTime();
        GetNodesWithLabel_and_PropertyKeyCypher(graphDB, label, PropertyKey);
        end_time = System.nanoTime();
        difference2 = end_time - start_time;
        System.out.println("Cypher time: " + difference2);

        tx.success();
    }
    System.out.println("====================================");
    System.out.println("difference in nanoseconds : "+(difference2-difference1));
    System.out.println("Done successfully");

}
}

------------------------------------------------------------------------

Building neo4j_0 1.0-SNAPSHOT

--- exec-maven-plugin:1.2.1:exec (default-cli) @ neo4j_0 ---
==================JavaApi==================
Key : name and Value: Steve 
Key : name and Value: Linda 
Key : name and Value: Michael 
Key : name and Value: Rebecca 
java time: 43800364
==================Cypher==================
Key : name and Value: Steve 
Key : name and Value: Linda 
Key : name and Value: Michael 
Key : name and Value: Rebecca 
Cypher time: 1583408758
====================================
difference in nanoseconds : 1539608394
Done successfully
------------------------------------------------------------------------
BUILD SUCCESS
a.s.p.
  • 328
  • 1
  • 3
  • 12
1

You'll rapidly find you might want to execute cypher queries from inside of java to do this kind of querying.

String query = "MATCH (n:Label) where n.username =~ ".*foo regex.*" RETURN n;";
try ( Transaction ignored = db.beginTx();
      Result result = db.execute(query) )
{
    while ( result.hasNext() )
    {
         // Do nifty stuff with results.
    }
}

The regular embedded API methods you're using aren't going to support regex or a great deal of other things, I'd suggest using cypher except for very simple cases (like "get node by property and value")

FrobberOfBits
  • 17,634
  • 4
  • 52
  • 86
  • 1
    Thanks @FrobberOfBits. I was following the documentation on traversals (http://neo4j.com/docs/stable/tutorials-java-embedded-traversal.html) and I wanted to add a bit more complexity to my query (basically filtering/ selecting a subset of nodes to do my analysis from, not just one node). So, is there any performance impact to using the embedded Cypher vs. the embedded API? – Jeff G. Apr 22 '15 at 22:15
  • The performance impact is that usually cypher will be faster! Hand-written traversals can be faster if you know your data really well, but in many common use cases using cypher will actually be superior I think because 2.2 has a cost-based planner, exploits all available indexes, etc - which may or may not be true of a traversal you write. – FrobberOfBits Apr 23 '15 at 02:40