Retrieving exact node id in neo4j cypher - java

I'm using neo4j-jdbc 2.3.2 as my neo4j client for java. When I executed following cypher query
match(p:Person) where p.id_number='761201948V' return p.id; it will return P2547228 as node id. I feel like id is same as other properties of the node as I can use it inside where clauses. But here I'm expecting an integer which can use inside this query START p=node('node.id') return p; Is this id is an internal thing to neo4j db? and is there a way to retrieve this id?
From the following two cyphers what is most efficient one?(if both referring same node)
START p=node('2547223') return p;
match(p:Person) where p.id='P2547228' return p;

You have to use the ID(x) function for this. Note, that ID(x) and x.id are a complete different thing. The former returns the internal node/relationship id managed by Neo4j itself. The latter gives the id property which is managed by the user and not by the database itself.
Also note, that a node/relationship ID is always numeric.
Using START is pretty much old school and shouldn't be used any more (except for accessing manual indexes):
start p=node(2547228) return p
This one is a equivalent statement. It is highly efficient since it just needs to do a simple seek operation on the node store:
match(p:Person) where id(p)=2547228 return p;
Looking for a property requires either a node label scan or a schema index lookup:
match(p:Person) where p.id=2547228 return p;
Just check out the query plans on your own by prefixing the statement with PROFILE.

Related

Querying on Collection attribute in Corda

I'm trying to search value inside Corda unconsumed states on a collection Field.
I'm able to search on String field using -
Field uniqueAttributeName = MySchema.PersistentIOU.class.getDeclaredField("fieldname");
CriteriaExpression uniqueAttributeEXpression = Builder.equal(uniqueAttributeName, "valueToSearch");
QueryCriteria customCriteria = new QueryCriteria.VaultCustomQueryCriteria(uniqueAttributeEXpression);
result = rpcOps.vaultQueryByCriteria(customCriteria, MyState.class).getStates();
Above worked fine when "fieldname" is String but I have another field which is List and I'm not sure how to search inside List for a specific value.
Please assist.
After a quick chat with #Roger3cev, we think the best way is to amend your ORM wrapper such that you have a parent - child relationship between the state and the list of fields you want to have in that list. Once you do this, you can use the JDBC connection available to you to query against the child state and then use the relationship to the parent to get the Corda state.

Failed to make bulk upsert using mongo

I'm trying to do upsert using mongodb driver, here is a code:
BulkWriteOperation builder = coll.initializeUnorderedBulkOperation();
DBObject toDBObject;
for (T entity : entities) {
toDBObject = morphia.toDBObject(entity);
builder.find(toDBObject).upsert().replaceOne(toDBObject);
}
BulkWriteResult result = builder.execute();
where "entity" is morphia object. When I'm running the code first time (there are no entities in the DB, so all of the queries should be insert) it works fine and I see the entities in the database with generated _id field. Second run I'm changing some fields and trying to save changed entities and then I receive the folowing error from mongo:
E11000 duplicate key error collection: statistics.counters index: _id_ dup key: { : ObjectId('56adfbf43d801b870e63be29') }
what I forgot to configure in my example?
I don't know the structure of dbObject, but that bulk Upsert needs a valid query in order to work.
Let's say, for example, that you have a unique (_id) property called "id". A valid query would look like:
builder.find({id: toDBObject.id}).upsert().replaceOne(toDBObject);
This way, the engine can (a) find an object to update and then (b) update it (or, insert if the object wasn't found). Of course, you need the Java syntax for find, but same rule applies: make sure your .find will find something, then do an update.
I believe (just a guess) that the way it's written now will find "all" docs and try to update the first one ... but the behavior you are describing suggests it's finding "no doc" and attempting an insert.

Neo4j slow cypher query in embedded mode

I have a huge graphdatabase with authors, which are connected to papers and papers a connected to nodes which contains meta information of the paper.
I tried to select authors which match a specific pattern and therefore I executed the following cypher statement in java.
String query = "MATCH (n:AUTHOR) WHERE n.name =~ '(?i).*jim.*' RETURN n";
db.execute(query);
I get a resultSet with all "authors" back. But the execution is very slow. Is it, because Neo4j writes the result into the memory?
If I try to find nodes with the Java API, it is much faster. Of course, I am only able to search for the exact name like the following code example, but it is about 4 seconds faster as the query above. I tested it on a small database with about 50 nodes, whereby only 6 of the nodes are authors. The six author are also in the index.
db.findNodes(NodeLabel.AUTHOR, NodeProperties.NAME, "jim knopf" );
Is there a chance to speed up the cypher? Or a possiblity to get all nodes via Java API and the findNodes() method, which match a given pattern?
Just for information, I created the index for the name of the author in java with graph.schema().indexFor(NodeLabel.AUTHOR).on("name").create();
Perhaps somebody could help. Thanks in advance.
EDIT:
I run some tests today. If I execute the query PROFILE MATCH (n:AUTHOR) WHERE n.name = 'jim seroka' RETURN n; in the browser interface, I have only the operator NodeByLabelScan. It seems to me, that Neo4j does not automatic use the index (Index for name is online). If I use a the specific index, and execute the query PROFILE MATCH (n:AUTHOR) USING INDEX n:AUTHOR(name) WHERE n.name = 'jim seroka' RETURN n; the index will be used. Normally Neo4j should use automatically the correct index. Is there any configuration to set?
I also did some testing in the embedded mode again, to check the performance of the query in the embedded mode. I tried to select the author "jim seroka" with db.findNode(NodeLabel.AUTHOR, "name", "jim seroka");. It works, and it seems to me that the index is used, because of a execution time of ~0,05 seconds.
But if I run the same query, as I executed in the interface and mentioned before, using a specific index, it takes ~4,9 seconds. Why? I'm a little bit helpless. The database is local and there are only 6 authors. Is the connector slow or is the creation of connection wrong? OK, findNode() does return just a node and execute a whole Result, but four seconds difference?
The following source code should show how the database will be created and the query is executed.
public static GraphDatabaseService getNeo4jDB() {
....
return new GraphDatabaseFactory().newEmbeddedDatabase(STORE_DIR);
}
private Result findAuthorNode(String searchValue) {
db = getNeo4jDB();
String query = "MATCH (n:AUTHOR) USING INDEX n:AUTHOR(name) WHERE n.name = 'jim seroka' RETURN n";
return db.execute(query);
}
Your query uses a regular expression and therefore is not able to use an index:
MATCH (n:AUTHOR) WHERE n.name =~ '(?i).*jim.*' RETURN n
Neo4j 2.3 introduced index supported STARTS WITH string operator so this query would be very performant:
MATCH (n:Author) WHERE n.name STARTS WITH 'jim' RETURN n
Not quite the same as the regular expression, but will have better performance.

Query Node from Neo4j by using java

Now I am using RESTFul API to interface with Neo4j. My issue is: for example I have already created a Node1 in Neo4j. Then I just want to create a Node2 and a relationship to connect to Node1. I know I need to query node from Neo4j and return a node. But how to do it? I am new in Neo4j please help.
And I have already build a delete function by using java to delete all nodes and relationships in Neo4j. Here is my code:
public String deleteAllNodeOrRelation() throws ClientHandlerException,
UniformInterfaceException, JDOMException {
String cypherPayload = "{\"query\": \"START a=node(*) MATCH a-[r?]-() DELETE a,r RETURN a\", \"params\":{}}";
String user_name = getUserName(cypherPayload);
return user_name;
}
is the query node function similar with this delete function? and to be noticed, I have properties stored in each node. The property name is "title". Someone told me I can query "title" to search and return the node1. But I still dont know how to do it....
Yes, you would have to enable auto-indexes for your domain-keys just do:
START u1=node:node_auto_index(name={user1}),
u2=node:node_auto_index(name={user2})
CREATE (u1)-[:KNOWS]->(u2)
you pass user1 and user2 as parameters to your function and to the cypher query call.
For some ways of how to call cypher from Java see: https://github.com/jexp/cypher-http-examples

Can I use a manually created index and query nodes using Cypher?

Here I have created a manual/legacy index and added some nodes with certain properties into it.
IndexManager indexy = graphdb.index();
Index<Node>indexery = indexy.forNodes("Main_Twitter_Index");
indexery.add(one,"Name",one.getProperty("Name"));
indexery.add(one,"Email",one.getProperty("Email"));
indexery.add(four,"Name",four.getProperty("Name"));
indexery.add(four,"Email",four.getProperty("Email"));
Now, to query the nodes of that index neo4j suggests query, which uses a key-value pair binding. My question is can I query the same nodes added into the manual index using a simple cypher query like,
START n=node:Main_Twitter_Index(Name = 'Akina')
RETURN n
Which version of Neo4j are you using? The method you describe is the typical index search for anything before 2.0, before they added schema indexing. Your query should work, even in 2.0. Are you having problems running it?

Categories

Resources