Neo4j Cypher chain output from match query to APOC - neo4j

I wanted to make use of the Neo4j Cypher apoc.index.search procedure. I am currently using the Neo4j CE 3.1.0. I have successfully set up and tested the procedure as a stand-alone query such as:
call apoc.index.search("Contact2", "Contact2.FirstName:monica~")
Now, I want to do a MATCH query first to fetch a set of nodes, and spool the FirstNames found into calling this APOC procedure on Contact2 node to see if I can find any similar in the Contact2 node and the corresponding weight.
Is that possible? I have tried several iterations using the WITH keyword but to no avail. Thanks.

You can add each firstName value as separate fuzzy search terms to the query string passed to apoc.index.search. For example:
MATCH (f:Foo)
WITH REDUCE(
s = 'Contact2.FirstName:', n IN COLLECT(DISTINCT f.firstName) |
s + n + '~ '
) AS query
CALL apoc.index.search("Contact2", query)
...

#cybersam thank you for your answer. I did not try yours but I also just solved this on my own (after days of trying). My syntax is as follows:
// Contact1 is my source table. Contact2 is my destination table
MATCH (a:Contact1) WITH a.FirstName AS A
CALL apoc.index.search("Contact2", "Contact2.FirstName:" + A + "~")
YIELD node, weight RETURN *
I am not sure if that is the best way but it worked for me

Related

Finding nodes not matching query in cypher

We have build up a NEO4j database with sample network data in it. We are currently trying to find a query to find NOT matching nodes.
We have 10 nodes in database and we get 8 of them by using the following query:
match(n:nodeType)-[r:binded]-(m.nodetype2)-[z:binded]-(t:nodeType) where n.workingMode='Working' and t.workingMode='Protection' return n
What we want is finding the two nodes which does not satify above condition.
I have found some entires mentioning the usage of NOT x IN y and tried a few solutions including
match(a) where a.workingMode ='Working'
match(n:nodeType)-[r:binded]-(m.nodetype2)-[z:binded]-(t:nodeType) where n.workingMode='Working' and t.workingMode='Protection'
and NOT a.id IN n.id
return a
but that returns 10 and others i have tried provided either 10 or 0 results.
Thanks in advance
You can pass the result of your first statement to the second statement of the query as a list and then use NOT IN to exclude these nodes:
MATCH(n:nodeType)-[r:binded]-(m.nodetype2)-[z:binded]-(t:nodeType)
WHERE n.workingMode='Working' AND t.workingMode='Protection'
WITH collect(n) as ns
MATCH (a:nodeType)
WHERE a.workingMode ='Working' AND NOT a IN ns
RETURN a

Cypher query fails with variable length paths when trying to find all paths with unique node occurences

I have a highly interconnected graph where starting from a specific node
i want to find all nodes connected to it regardless of the relation type, direction or length. What i am trying to do is to filter out paths that include a node more than 1 times. But what i get is a
Neo.DatabaseError.General.UnknownError: key not found: UNNAMED27
I have managed to create a much simpler database
in neo4j sandbox and get the same message again using the following data:
CREATE (n1:Person { pid:1, name: 'User1'}),
(n2:Person { pid:2, name: 'User2'}),
(n3:Person { pid:3, name: 'User3'}),
(n4:Person { pid:4, name: 'User4'}),
(n5:Person { pid:5, name: 'User5'})
With the following relationships:
MATCH (n1{pid:1}),(n2{pid:2}),(n3{pid:3}),(n4{pid:4}),(n5{pid:5})
CREATE (n1)-[r1:RELATION]->(n2),
(n5)-[r2:RELATION]->(n2),
(n1)-[r3:RELATION]->(n3),
(n4)-[r4:RELATION]->(n3)
The Cypher Query that causes this issue in the above model is
MATCH p= (n:Person{pid:1})-[*0..]-(m)
WHERE ALL(c IN nodes(p) WHERE 1=size(filter(d in nodes(p) where c.pid = d.pid)) )
return m
Can anybody see what is wrong with this query?
The error seems like a bug to me. There is a closed neo4j issue that seems similar, but it was supposed to be fixed in version 3.2.1. You should probably create a new issue for it, since your comments state you are using 3.2.5.
Meanwhile, this query should get the results you seem to want:
MATCH p=(:Person{pid:1})-[*0..]-(m)
WITH m, NODES(p) AS ns
UNWIND ns AS n
WITH m, ns, COUNT(DISTINCT n) AS cns
WHERE SIZE(ns) = cns
return m
You should strongly consider putting a reasonable upper bound on your variable-length path search, though. If you do not do so, then with any reasonable DB size your query is likely to take a very long time and/or run out of memory.
When finding paths, Cypher will never visit the same node twice in a single path. So MATCH (a:Start)-[*]-(b) RETURN DISTINCT b will return all nodes connected to a. (DISTINCT here is redundant, but it can affect query performance. Use PROFILE on your version of Neo4j to see if it cares and which is better)
NOTE: This works starting with Neo4j 3.2 Cypher planner. For previous versions of
the Cypher planner, the only performant way to do this is with APOC, or add a -[:connected_to]-> relation from start node to all children so that path doesn't have to be explored.)

Cypher - How to query multiple Neo4j Node property fragments with "STARTS WITH"

I'm looking for a way to combine the Cypher "IN" and "STARTS WITH" query. In other words I'm looking for a way to look up nodes that start with specific string sequences that are provided as Array using IN.
The goal is to have the query run in as less as possible calls against the DB.
I browsed the documentation and played around with Neo4j a bit but wasn't able to combine the following two queries into one:
MATCH (a:Node_type_A)-[]->(b:Node_type_B)
WHERE a.prop_A IN [...Array of Strings]
RETURN a.prop_A, COLLECT ({result_b: b.prop_B})
and
MATCH (a:Node_type_A)-[]->(b:Node_type_B)
WHERE a.prop_A STARTS WITH 'String'
RETURN a.prop_A, b.prop_B
Is there a way to combine these two approaches?
Any help is greatly appreciated.
Krid
You'll want to make sure there is an index or unique constraint (whichever is appropriate) on your :Node_type_A(prop_A) to speed up your lookups.
If I'm reading your requirements right, this query may work for you, adding your input strings as appropriate (parameterize them if you can).
WITH [...] as inputs
UNWIND inputs as input
// each string in inputs is now on its own row
MATCH (a:Node_type_A)
WHERE a.prop_A STARTS WITH input
// should be an fast index lookup for each input string
WITH a
MATCH (a)-[]->(b:Node_type_B)
RETURN a.prop_A, COLLECT ({result_b: b.prop_B})
Something like this should work:
MATCH (a:Node_type_A)-[]->(b:Node_type_B)
WITH a.prop_A AS pa, b.prop_B AS pb
WITH pa, pb,
REDUCE(s = [], x IN ['a','b','c'] |
CASE WHEN pa STARTS WITH x THEN s + pb ELSE s END) AS pbs
RETURN pa, pbs;

Post processing on UNION result cypher query neo4j

I have written below query using lucene indexing . I know UNION doesn't have pagination support in neo4j . I want to post process the
final result of this query to paginate the result .
START user=node:peopleSearch('username:abhay*') RETURN user , user.createdDate as time UNION START rel= Relationship:peopleSearch('skillName:Java23') RETURN StartNode(rel) as user , StartNode(rel).createdDate as time
I have followed this link . But it giving me error on UNION RESULT .
I need to post process the union final result to paginate it
The referenced github issue is not yet resolved, so post processing of UNION is not yet possible.
As a workaround in the meantime you can split up your query into two queries. The first one combines the index lookups and returns node ids:
START user=node:peopleSearch('username:abhay*') RETURN id(user) as id
UNION
START rel= Relationship:peopleSearch('skillName:Java23') RETURN id(StartNode(rel)) as id
On client side, collect the returned IDs into an array and submit the second query using a cypher parameter:
MATCH (n)
WHERE ID(n) IN {myIdArray}
WITH n
// placeholder for rest of this query
where the parameter value of myIdArray is the returned IDs from step1.
I had a similar question a few weeks ago, and it turns out Cypher currently does not support post-UNION processing.
This means that you should filter both inputs of the union using the same condition.
Alternatively (as mentioned in this answer), if you can use APOC, you can post-process the results of a query:
CALL apoc.cypher.run("... UNION ...", NULL) YIELD n, r, x
WHERE ...
RETURN n, r, x;
Update: this is now possible in Neo4j 4.0 using the CALL {subquery} construct.

How to list out all the nodes which are having common properties in neo4j

I'm having 4 nodes A,B,C,D having following properties,
A:{works_in:"wipro"},{designation:"SE"}
B:{works_in:"CTS"},{designation:"SSE"}
C:{works_in:"CGI"},{designation:"SE"}
D:{works_in:"UHG"},{designation:"SSE"}
Now i want to display all the nodes which is having similar properties either works_in/designation
You can try something like:
MATCH (a:YourLabel)
WITH a
MATCH (b:YourLabel)
WHERE a <> b AND (b.works_in = a.work_in OR b.designation = a.designation)
RETURN a, COLLECT(b) AS similar
This will initially match all your nodes and then use each node as the source for a new query. the a <> b will stop nodes matching themselves.
I have tried with following query, its working fine
MATCH (A),(B)
WHERE A. works_in =B. works_in
RETURN A. works_in as Node1_and_Node2_working_in;
but the problem i'm facing here is each node is matching self. so result is coming
like,
Node1_and_Node2_working_in
wipro (A-to-A)
cts (B-to-B)
cgi (C-to-C)
uhg (D-to-D)
Can we solve this with any built in command or property. if so please share your view on it.
Hej Pavan, i would do it like this:
This Query will return all Node which works_in CGI or CTS and have a designation like SE or SSE.
MATCH (n) WHERE n.works_in =~ 'C.*' AND n.designation =~ '(?i)S.*' return n
This will return the Nodes B and C.
With the =~ Operator you can use Regular Expressions in your Query
Maybe you also want to have a quick look in the Neo4J Docs
If the query should only return Nodes which fit exactly to works_in, then use
MATCH (n) WHERE n.works_in = 'WinPro'
or
MATCH (n) WHERE n.designation = 'SE'
Another Idea would be to create Node with properties like Name and E-Mail and create Node like Skill (CGI, Java, WinPro) or Project and connect them with Relationships like WORKS_IN or is LOCATED_IN...
Patrick

Resources