Reputation: 1601
Given a keyword, I would like to find all the papers that contain the keyword, their references and the authors of all the papers. I've tried using 3 approaches.
approach 1 combining the results into a list, but this leads to duplicate entries in the list (papers).
MATCH (k:keyword)-[AREAOF]->(f:fieldOfStudy {fieldName: "fos1"})
WITH k
MATCH (p:paper)-[:CONTAINS]->(k)
WITH p
MATCH (p)-[:REFERENCES]->(r:paper)
WITH p,r
MATCH (c:paper)-[:REFERENCES]->(p)
WITH [c,p,r] as papers
MATCH (a:author)-[:PUBLISHED]->(p:paper)
WHERE p in papers
return a,p
approach 2 - Using + operator I tried to do something similar to this, but I get a type mismatch error.
MATCH (k:keyword)-[AREAOF]->(f:fieldOfStudy {fieldName: "fos1"})
WITH k
MATCH (p:paper)-[:CONTAINS]->(k)
WITH p
MATCH (p)-[:REFERENCES]->(r:paper)
WITH p,r
MATCH (c:paper)-[:REFERENCES]->(p)
RETURN p+r
Error:
Type mismatch: expected List<Node> but was Node (line 8, column 14 (offset: 229))
" return p+r"
^
approach 3 - using UNION
The first approach fails since each results shows the represents the connection between papers. I.e c-[:REFERENCES]->p-[:REFERENCES]->r. To obtain a 1 dimensional result I tried to use UNION. This works and obtains a unique list of the papers, however I cannot manage to use the output to query for the authors.
MATCH (k:keyword)-[AREAOF]->(f:fieldOfStudy {fieldName: "fos1"})
WITH k
MATCH (p:paper)-[:CONTAINS]->(k)
RETURN p as papers
UNION
MATCH (k:keyword)-[AREAOF]->(f:fieldOfStudy {fieldName: "fos1"})
WITH k
MATCH (p:paper)-[:CONTAINS]->(k)
WITH p
MATCH (p)-[:REFERENCES]->(r:paper)
RETURN r as papers
UNION
MATCH (k:keyword)-[AREAOF]->(f:fieldOfStudy {fieldName: "fos1"})
WITH k
MATCH (p:paper)-[:CONTAINS]->(k)
WITH p
MATCH (c:paper)-[:REFERENCES]->(p)
RETURN c as papers
In this case, how can I take the final answer (papers) and find their authors? i.e
(a:author)-[:PUBLISHED]->(p:paper)
WHERE p in papers
Upvotes: 0
Views: 1643
Reputation: 30397
You can actually get all the papers you need quite easily by matching from papers using a 0-1 variable relationship, and omitting direction.
Here's how that might work:
MATCH (k:keyword)-[:AREAOF]->(:fieldOfStudy {fieldName: "fos1"})
MATCH (p:paper)-[:CONTAINS]->(k)
WITH p
MATCH (p)-[:REFERENCES*0..1]-(paper:Paper)
WITH DISTINCT paper
MATCH (a:author)-[:PUBLISHED]->(paper)
RETURN a, paper
The key is in the undirected :REFERENCES match:
MATCH (p)-[:REFERENCES*0..1]-(paper:Paper)
This will traverse 0 to 1 :REFERENCES relationships, meaning "paper" will include p, as well as any node linked to p through a :REFERENCES relationship in either direction, so you'll get papers that referenced p as well as papers that p referenced.
Upvotes: 1
Reputation: 1601
After some further research I used approach 1 then used UNWIND to convert the answer into a single list. Since this contained duplicates, I used distinct() to filter out duplicate entries. The result is as follows
MATCH (k:keyword)-[AREAOF]->(f:fieldOfStudy {fieldName: "fos1"})
WITH k
MATCH (p:paper)-[:CONTAINS]->(k)
WITH p
MATCH (p)-[:REFERENCES]->(r:paper)
WITH p,r
MATCH (c:paper)-[:REFERENCES]->(p)
WITH [c,p,r] as papers
UNWIND papers as pap
WITH distinct(pap) as papers
MATCH (a:author)-[:PUBLISHED]->(p:paper)
WHERE p in [papers]
return a,p
Upvotes: 1
Reputation: 5047
You can collect the papers to a list:
MATCH ...
WITH somePaper, collect(p) AS papers
WHERE somePaper IN papers
RETURN somePaper
Upvotes: 0