Hey I'm currently writing a Java application that accesses NEO4J via Spring Neo4J Driver.
I have a couple of nodes with arrays. No I'm trying to write an cypher Query that deletes an Element from an array of a matched node. If the element was the last one i would love to delete the complete node. To achive this I'm using apoc.do.when. You can find a simplified version of my query below.
MATCH (n:NODE) WHERE "Peter" IN n.NAMES
CALL apoc.do.when(size(n.NAMES) > 1, 'SET n.NAMES = [x IN n.NAMES WHERE x <> "Peter"]', 'DETACH DELETE n') YIELD value
RETURN value
My query is overall working fine, but I don't get the Result summary back anymore in my Java application.
I'm calling the query the following way:
ResultSummary output = driver.session().run(query.withParameters(params)).consume();
I know that the query is executed and deleting a node. I validated that by Neo4J browser, but the result summary says:
serverInfo=InternalServerInfo{address='localhost:7687', version='Neo4j/3.5.17'}, databaseInfo=InternalDatabaseInfo{name='null'}, queryType=READ_WRITE, counters=null, plan=null, profile=null, notifications=[], resultAvailableAfter=143, resultConsumedAfter=1}
Updates: 0
Delete: 0
Therefore i can not validate from my Javacode if the operation was successful. I assume that apoc.do.when does not promote the result summary from the query correctly. Is there anyway to fix this or do i need to validate this with a second query?
You can modify the Cypher query to return a result that indicates whether an update or deletion occurred. For example:
MATCH (n:NODE) WHERE "Peter" IN n.NAMES
CALL apoc.do.when(
size(n.NAMES) > 1,
'SET n.NAMES = [x IN n.NAMES WHERE x <> "Peter"] RETURN "updated" AS res',
'DETACH DELETE n RETURN "deleted" AS res') YIELD value
RETURN value.res AS res
Then your Java client can iterate through (or stream) the resulting records and count the number of updates and deletions.
Related
I want to update rows on a table which contains the following colums:
`parameter_name`(PRIMARY KEY),
`option_order`,
`value`.
I have a collection called parameterColletion which contains "parameterNames", "optionOrders" and "values". This collection does not have a fixed value, it can receive the quantity of parameters you want to.
Imagine I have 5 parameters inside my collection (I could have 28, or 10204 too) and I am trying to update the rows of the database using the next query. Example of query:
UPDATE insight_app_parameter_option
SET option_order IN (1,2,3,4,5), value IN ('a','b','c','d','e')
WHERE parameter_name IN ('name1', 'name2', 'name3', 'name4', 'name5')
But this isn't doing the job, instead it gives back an error which says You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'IN (1,2,3,4,5), value IN ('a','b','c','d','e') WHERE parameter_name IN ('name1'' at line 2
1,2,3,4,5 -> Represent the option orders inside parameterCollection.
'a','b','c','d','e' -> Represent the values inside parameterCollection.
'name1', 'name2', 'name3', 'name4', 'name5' -> Represent the names inside parameterCollection.
I know how to update each parameter by separate but i would like to do it all together. Here are some links I visited where people asked the same question but they used a fixed colletion of objects, not a mutable one.
MySQL - UPDATE multiple rows with different values in one query
Multiple rows update into a single query
SQL - Update multiple records in one query
That's not possible with MySQL. The error you are receiving is a syntax error. You are not able to set multiple values at once. This is the correct syntax to a UPDATE statement: (ref)
UPDATE [LOW_PRIORITY] [IGNORE] table_reference
SET assignment_list
[WHERE where_condition]
[ORDER BY ...]
[LIMIT row_count]
value:
{expr | DEFAULT}
assignment:
col_name = value
assignment_list:
assignment [, assignment] ...
You need to create separate UPDATEs for each row. I suggest executing all in a single transaction, if its the case.
The correct syntax for your example is:
UPDATE insight_app_parameter_option
SET option_order = 1, value = 'a'
WHERE parameter_name = 'name1';
UPDATE insight_app_parameter_option
SET option_order = 2, value = 'b'
WHERE parameter_name = 'name2';
UPDATE insight_app_parameter_option
SET option_order = 3, value = 'c'
WHERE parameter_name = 'name3';
...
I am trying out a simple test and so I have a simple stored procedure. It selects rows from a table
CREATE PROCEDURE [dbo].[Test_SQL_Connect]
as
BEGIN
SET NOCOUNT ON
select * from [dbo].[Test_Sqlconnector]
END
When I run exec [dbo].[Test_SQL_Connect] ..the output is
TagName TagValue Timestamp TagStatus
tag1 value1 2017-01-31 19:09:43.7570000 1
In Java, I have the following code(connection has been created earlier)
SQLServerCallableStatement cStatement =
(SQLServerCallableStatement)connection.prepareCall("{call dbo.Test_SQL_Connect}");
cStatement.execute();
After execution the value of cStatement.getUpdateCount() = -1 .
Would anyone know why the updatecount is -1 even though 1 record is returned?
This is the expected result of Statement.getUpdateCount()
Retrieves the current result as an update count; if the result is a
ResultSet object or there are no more results, -1 is returned.
This method should be called only once per result.
Also have a look at the javadoc of PreparedStatement.execute().
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.
I'm performing a test with CouchBase 4.0 and java sdk 2.2. I'm inserting 10 documents whose keys always start by "190".
After inserting these 10 documents I query them with:
cb.restore("190", cache);
Thread.sleep(100);
cb.restore("190", cache);
The query within the 'restore' method is:
Statement st = Select.select("meta(c).id, c.*").from(this.bucketName + " c").where(Expression.x("meta(c).id").like(Expression.s(callId + "_%")));
N1qlQueryResult result = bucket.query(st);
The first call to restore returns 0 documents:
Query 'SELECT meta(c).id, c.* FROM cache c WHERE meta(c).id LIKE "190_%"' --> Size = 0
The second call (100ms later) returns the 10 documents:
Query 'SELECT meta(c).id, c.* FROM cache c WHERE meta(c).id LIKE "190_%"' --> Size = 10
I tried adding PersistTo.MASTER in the 'insert' statement, but it neither works.
It seems that the 'insert' is not persisted immediately.
Any help would be really appreciated.
Joan.
You're using N1QL to query the data - and N1QL is only eventually consistent (by default), so it only shows up after the indices are recalculated. This isn't related to whether or not the data is persisted (meaning: written from RAM to disc).
You can try to change the scan_consitency level from its default - NOT_BOUNDED - to get consistent results, but that would take longer to return.
read more here
java scan_consitency options
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?