I have a String property in my nodes where the length of the String isn't fix.
Now i must search the right node by this property but i get a fixed length value from another System. For Example my Node has the Value '0123' but I get the Information '000123' for searching.
I need a function like left padding with Zeros and this in the Where Clause like
MATCH (a:LABEL) where leftPad(a.property, 6, '0') = '000123' return a
LIMIT 1
Is something like this possible with a good Performance?
You could do this:
MATCH (a:LABEL)
WHERE SUBSTRING('00000', 0, SIZE(a.property)) + a.property = '000123'
RETURN a
LIMIT 1;
Or, if all the characters are numeric, then you could do this:
MATCH (a:LABEL)
WHERE TOINT(a.property) = TOINT('000123')
RETURN a
LIMIT 1;
However, it would be even better if you could just store the property value as an integer in the first place, and also compare it to an integer, which would be the fastest. This might be very easy to do, depending on your situation.
MATCH (a:LABEL)
WHERE a.property = 000123
RETURN a
LIMIT 1;
Try it with reduce:
MATCH (a:LABEL)
WHERE REDUCE(lp='', n in RANGE(0,5-size(a.name)) | lp+'0')+a. a.property = '000123'
RETURN a
or try it with regular expression:
MATCH (a:LABEL)
WHERE a.property =~ '(0){0,3}123'
RETURN a
Related
Match(csav:CSAVHierarchy) with csav
Match(cx:CXCustomerHierarchy) with cx
Optional Match(csav)-[:CSAVCustomerHasChild]->(csa:CSAVHierarchy) where csa._type='CXCustomer' OR csa._type='CXCustomerBU'
Optional Match(cx)-[:CXCustomerHasChild]->(cxc:CXCustomerHierarchy) where cxc._type='CXCustomer' OR cxc._type='CXCustomerBU'
return
CASE
WHEN csa.ssid = cxc.ssid and csa.elementLabel = cxc.elementLabel
THEN "yes"
ELSE "No" END As result
with this query its giving cartesian issue and i want to carry forward both the nodes data for further use.
where I m lacking?
You can use the Apoc plugin (see https://neo4j-contrib.github.io/neo4j-apoc-procedures):
Match(n:Person{ssid:"1234"}) with collect(n) as nodes CALL apoc.refactor.mergeNodes(nodes) YIELD node RETURN node
This query may do what you want. It returns the unique cxc and csa pairs that pass all your tests.
MATCH (csa:CSAVHierarchy)
WHERE
(:CSAVHierarchy)-[:CSAVCustomerHasChild]->(csa) AND
csa._type='CXCustomer' OR csa._type='CXCustomerBU'
MATCH (cxc:CXCustomerHierarchy)
WHERE
(:CXCustomerHierarchy)-[:CXCustomerHasChild]->(cxc) AND
csa.ssid = cxc.ssid AND
csa.elementLabel = cxc.elementLabel AND
(cxc._type='CXCustomer' OR cxc._type='CXCustomerBU')
RETURN cxc, csa
For better performance, you should also create indexes on :CSAVHierarchy(_type) and :CXCustomerHierarchy(_type).
This the solution I came up with
MATCH(cxc:CXCustomerHierarchy)-[:_properties]->(auditnode)-->(spoke)
where cxc._type='CXCustomer' OR cxc._type='CXCustomerBU' AND spoke.start_date <= 1554272198875 <= spoke.end_date AND spoke.status = "Confirmed"
with cxc
OPTIONAL MATCH (cxc)<-[r:CXCustomerHasChild]-(parent) with cxc
MATCH(csav:CSAVHierarchy)-[:_properties]->(auditnode)-->(spoke) with cxc,csav
where csav._type='CXCustomer' OR csav._type='CXCustomerBU' AND spoke.start_date <= 1554272198875 <= spoke.end_date AND spoke.status = "Confirmed"
OPTIONAL MATCH (csav)<-[r:CSAVCustomerHasChild]-(parent) with csav,cxc
return
CASE
WHEN csav.sourceSystemId <> cxc.sourceSystemId , csav.elementLabel <> cxc.elementLabel
THEN csav.elementLabel
ELSE "SIMILAR DATA " END As result
This is in continuation of Neo4j: Listing node labels
I am constructing a dynamic MATCH statement to return the hierarchy structure & use the output as a Neo4j JDBC input to query the data from a java method:
MATCH p=(:Service)<-[*]-(:Anomaly)
WITH head(nodes(p)) AS Service, p, count(p) AS cnt
RETURN DISTINCT Service.company_id, Service.company_site_id,
"MATCH srvhier=(" +
reduce(labels = "", n IN nodes(p) | labels + labels(n)[0] +
"<-[:BELONGS_TO]-") + ") WHERE Service.company_id = {1} AND
Service.company_site_id = {2} AND Anomaly.name={3} RETURN " +
reduce(labels = "", n IN nodes(p) | labels + labels(n)[0] + ".name,");
The output is as follows:
MATCH srvhier=(Service<-[:BELONGS_TO]-Category<-[:BELONGS_TO]-SubService<-
[:BELONGS_TO]-Assets<-[:BELONGS_TO]-Anomaly<-[:BELONGS_TO]-) WHERE
Service.company_id = {1} and Service.company_site_id = {21} and
Anomaly.name={3} RETURN Service.name, Category.name, SubService.name,
Assets.name, Anomaly.name,
The problem I am seeing:
The "BELONGS_TO" gets appended to my last node
Line 2: Assets<-[:BELONGS_TO]-Anomaly**<-[:BELONGS_TO]-**
Are there string functions (I have looked at Substring..) that can be used to remove it? Or can I use a CASE statement with condition n=cnt to append "BELONGS_TO"?
The same problem persists with my last line:
Line 5: Assets.name,Anomaly.name**,** - the additional "," that I need to eliminate.
Thanks.
I think you need to introduce a case statement into the reduce clause something like this snippet below. If the node isn't the last element of the collection then append the "<-[:BELONGS_TO]-" relationship. If it is the last element then don't append it.
...
reduce(labels = "", n IN nodes(p) |
CASE
WHEN n <> nodes(p)[length(nodes(p))-1] THEN
labels + labels(n)[0] + "<-[:BELONGS_TO]-"
ELSE
labels + labels(n)[0]
END
...
Cypher has a substring function that works basically like you'd expect. An example: here's how you'd return everything but the last three characters of a string:
return substring("hello", 0, length("hello")-3);
(That returns "he")
So you could use substring to trim the last separator off of your query that you don't want.
But I don't understand why you're building your query in such a complex way; you're using cypher to write cypher (which is OK) but (and I don't understand your data model 100%) it seems to me like there's probably an easier way to write this query.
How do I get with cypher the minimum value of array with properties?
MATCH (n)-[r]->(m) RETURN n,m,min(r.timestamps)
Above query does not work.
r has an array with timestamps r.timestamps
How to get the lowest value of timestamps?
You can use unwind:
MATCH (n)-[r]->(m)
UNWIND r.timestamps as timestampts
RETURN n, m, min(timestampts)
I found an answer like this, but it looks ugly
MATCH
(h1)-[r]-(h2)
RETURN h1, h2,
reduce(minTimestamp = 999999999999999999, t IN r.timestamps | CASE WHEN minTimestamp < t THEN minTimestamp ELSE t END)
Is there any way to use the results of a UNION in another sub-query using a WITH clause?
I'm looking for something like
(
MATCH (me:Person)-[:RATES]->(r:Rating)-[:RATED_BY]->(them:Person)
WHERE me.ident = {id} AND r.date = {date}
RETURN them
UNION ALL
MATCH (me:Person)<-[:RATED_BY]-(r:Rating)<-[:RATES]-(them:Person)
WHERE me.edent = {id} AND r.date = {date}
RETURN them
)
WITH them
RETURN them.name, COUNT( them.name) as ratingCount
ORDER BY ratingCount DESC
LIMIT 10
only nothing like this is supported by cypher.
And yes, I know that in this case I should be using
MATCH (me:Person)-[:RATES|RATED_BY]-(r:Rating)-[:RATES|RATED_BY]-(them:Person)
WHERE me.ident = {id} AND r.date = {date}
RETURN them.name, COUNT( them.name) as ratingCount
ORDER BY ratingCount DESC
LIMIT 10
which is fine and dandy, but I think that I'm going to get some more complex requests down the road where this won't work.
The following query fails:
MATCH n:User
WHERE n.email = "test"
SET n = {data}, n.created = timestamp()
RETURN n
Is this expected? Is it a bug? Is there a workaround? Do I have to compute the timestamp and send it along with {data}?
A slight modification of your statement using 2 SET clauses works:
MATCH n:User
WHERE n.email = "test"
SET n = {data}
SET n.created = timestamp()
RETURN n