I have the following query
MATCH (e) WHERE SIZE((e:Customer)<-[:Transaction]-()) <> 0
AND SIZE(()<-[:Transaction]-(e)) <> 0
MATCH path = (e)-[:Transaction*..10]-(e) return path
I am getting the expected results with the above query.
I am trying to parallelize this query with the following query
MATCH (e:Customer) WHERE SIZE((e)<-[:Transaction]-()) <> 0 AND SIZE(()<-[:Transaction]-(e)) <> 0 WITH
collect(e.ID) AS users CALL apoc.cypher.mapParallel2("match (e:Customer)-[:Transaction*..10]->(e)
where e.ID=_ return e.ID as ll",{},users,10) yield value return value.ll
this query doesn't return anything. Kindly, please help me with this.
Does this query, which is also more efficient, work for you?
MATCH (e:Customer)
WHERE (e)<-[:Transaction]-() AND ()<-[:Transaction]-(e)
WITH collect(e) AS users
CALL apoc.cypher.mapParallel2(
"match (_)-[:Transaction*..10]->(_) return _.ID as ll",
{},users,10) YIELD value
RETURN value.ll
Related
I have the following params in my Neo4J:
{
"lists": [
{
"from": "someone",
"to": "somebody"
}
]
}
And the following query:
MATCH (c:Concept{name:'infranodus'}) WITH c, $lists AS list
UNWIND CASE WHEN list = [{}] THEN [null] ELSE list END AS l
WITH l
MATCH (cp1:Concept{name:l.from})
WITH cp1
MATCH (cp2:Concept{name:'somebody'})
RETURN cp1,cp2;
The query above will work.
However, if I replace l.from with a non-existent parameter, e.g. l.about, then — as the match doesn't happen — the second cp2 match doesn't fire.
How can I change this behavior and continue executing this query even if cp1 is not found? Maybe there's a way to pass on a dummy variable as a result?
MATCH (c:Concept{name:'infranodus'}) WITH c, $lists AS list
UNWIND CASE WHEN list = [{}] THEN [null] ELSE list END AS l
WITH l
MATCH (cp1:Concept{name:l.about})
WITH cp1
MATCH (cp2:Concept{name:'somebody'})
RETURN cp1,cp2;
Use OPTIONAL MATCH. If there is no match is found, then it will use NULL for the missing part of the pattern. It is similar to outer join in SQL.
NEW:
OPTIONAL MATCH (cp1:Concept{name:l.about})
OLD:
MATCH (cp1:Concept{name:l.about})
You can maybe replace it with an IN predicate ?
For eg :
WITH {from: 'Matt Olg', about: 'Matthew Olg'}
AS l
MATCH (n:Person)
WHERE n.name IN [l.from, l.to]
RETURN n.name
╒══════════╕
│"n.name" │
╞══════════╡
│"Matt Olg"│
└──────────┘
I have a use case where I am trying to optimize my Neo4j db calls and code by using the RETURN CASE WHEN THEN clauses in Cypher to run different queries depending on the WHEN result. This is my example:
MATCH (n {email: 'abc123#abc.com'})
RETURN
CASE WHEN n.category='Owner' THEN MATCH '(n)-[r:OWNS]->(m)'
WHEN n.category='Dealer' THEN MATCH (n)-[r:SUPPLY_PARTS_FOR]->(m)
WHEN n.category='Mechanic' THEN MATCH (n)-[r:SERVICE]-(m) END
AS result;
I am not sure this is legal but this is what I want to achieve. I am getting syntax errors like Invalid input '>'. How can I achieve this in the best manner?
EDIT for possible APOC solution:
This was my plan before discovering the limitation of FOREACH...
MATCH (user:Person {email:{paramEmail}})
FOREACH (_ IN case when 'Owner' = {paramCategory} then [1] else [] end|
SET user:Owner, user += queryObj
WITH user, {paramVehicles} AS coll
UNWIND coll AS vehicle
MATCH(v:Vehicles {name:vehicle})
CREATE UNIQUE (user)-[r:OWNS {since: timestamp()}]->(v)
SET r += paramVehicleProps
)
FOREACH (_ IN case when 'Mechanic' = {Category} then [1] else [] end|
SET user:Owner, user += queryObj
WITH user, {paramVehicles} AS coll
….
)
FOREACH (_ IN case when 'Dealer' = {paramCategory} then [1] else [] end|
SET user:Owner, user += queryObj
WITH user, {paramVehicles} AS coll
…...
)
RETURN user,
CASE {paramCategory}
WHEN 'Owner' THEN [(n)-[r:OWNS]->(m) | m and r]
WHEN 'Dealer' THEN [(n)-[r:SUPPLY_PARTS_FOR]->(m) | m]
WHEN 'Mechanic' THEN [(n)-[r:SERVICE]-(m) | m]
END AS result`,{
paramQueryObj: queryObj,
paramVehicles: makeVehicleArray,
paramVehicleProps: vehiclePropsArray,
paramSalesAgent: dealerSalesAgentObjarray,
paramWarehouseAgent: dealerWarehouseAgentObjarray
}).....
does anyone know to convert this using apoc.do.when()? note I need 'm' and 'r' in the first THEN.
You should still use a label in your first match, otherwise you get a full database scan and not a index lookup by email!!
for your query you can use pattern comprehensions:
MATCH (n:Person {email: 'abc123#abc.com'})
RETURN
CASE n.category
WHEN 'Owner' THEN [(n)-[r:OWNS]->(m) | m]
WHEN 'Dealer' THEN [(n)-[r:SUPPLY_PARTS_FOR]->(m) | m]
WHEN 'Mechanic' THEN [(n)-[r:SERVICE]-(m) | m] END
AS result;
It is also possible to use apoc.do.case: https://neo4j.com/labs/apoc/4.4/overview/apoc.do/apoc.do.case/
CALL apoc.do.case([
false,
'CREATE (a:Node{name:"A"}) RETURN a AS node',
true,
'CREATE (b:Node{name:"B"}) RETURN b AS node'
],
'CREATE (c:Node{name:"C"}) RETURN c AS node',{})
YIELD value
RETURN value.node AS node;
How to get the count of more than one nodes.
MATCH (n1:node1)
MATCH (n2:node2)
MATCH (n3:node3) where n3.status = "active"
return count(n1) as countOfNode1,
count(n2) as countOfNode2,
count(n3) as countOfNode3
This query is returning duplicated result as
countOfNode1 = 0
countOfNode2 = 0
countOfNode3 = 0
where the real count is
countOfNode1 = 0
countOfNode2 = 3
countOfNode3 = 1
How to do this?
Using 'distinct' also does not solve the problem.
Given as:
return count(distinct n1) as countOfNode1,
count(distinct n2) as countOfNode2,
count(distinct n3) as countOfNode3
One possibility I'm thinking of is this
MATCH (n1:node1) WITH count(n1) as countOfNode1
MATCH (n2:node2) WITH count(n2) as countOfNode2
MATCH (n3:node3) where n3.status = "active" WITH count(n3) as countOfNode3
return countOfNode1,
countOfNode2,
countOfNode3
Or maybe
MATCH (n1:node1), (n2:node2),(n3:node3 {status:"active"} )
return count(n1) as countOfNode1,
count(n2) as countOfNode2,
count(n3) as countOfNode3
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
Can I put condition in count()? Let me explain.
START me=node:node_auto_index(UserProfileID = '1'), other=node(*)
MATCH pMutualFriends=me-[r?:friends]-mf-[r1:friends]-other
WHERE other.UserName? =~ '(?i)dh.*' AND other.UserProfileID? <> 1
RETURN me.EMailID, other.EMailID,other.UserProfileID, other.UserName, r.ApprovalStatus, COUNT(pMutualFriends) AS mutualCount
in above query can I user like this.
COUNT(pMutualFriends where r.ApprovalStatus = 1 AND r1.ApprovalStatus =1 )
Or may be in other way?
Thanks
The filter function should help you. If you need further assistence, please provide a data sample on http://console.neo4j.org and share it here.
As an example:
START me=node:node_auto_index(UserProfileID = '1'), other=node(*)
MATCH pMutualFriends=me-[r?:friends]-mf-[r1:friends]-other
WHERE other.UserName? =~ '(?i)dh.*' AND other.UserProfileID? <> 1
RETURN me.EMailID, other.EMailID,other.UserProfileID, other.UserName,
count(filter(x IN r.ApprovalStatus: x=1)),
count(filter(x IN r1.ApprovalStatus: x=1))