I have a method which I pass the title of an existing node, and two lists. One containing titles for new nodes and one containing the count which should be added to the new relationships as a property. Both lists contain the same number of items.
I unwind the list of new articles and can successfully add the new nodes using this code:
public async Task AddArticlesWithRelationshipsAsync(List<string> newArticleTitles, string linkedFromArticle, List<int> count)
{
await client
.Cypher
.Unwind(newArticleTitles, "newArticleTitle")
.Match("(linkedFromArticle:Article)")
.Where("linkedFromArticle.title = { linkedFromArticle}")
.WithParam("linkedFromArticle", linkedFromArticle)
.Merge("(newArticle: Article { title: newArticleTitle } )")
.Merge("(newArticle)< -[:REFERENCES { count: 500 }]-(linkedFromArticle)")
.ExecuteWithoutResultsAsync();
}
However, this has a hardcoded count of 500. I am struggling to make use of the count of <int>
. My best attempt so far is to also unwind the count
list:
public async Task AddArticlesWithRelationshipsAsync(List<string> newArticleTitles, string linkedFromArticle, List<int> count)
{
await client
.Cypher
.Unwind(newArticleTitles, "newArticleTitle")
.Unwind(count, "count")
.Match("(linkedFromArticle:Article)")
.Where("linkedFromArticle.title = { linkedFromArticle}")
.WithParam("linkedFromArticle", linkedFromArticle)
.Merge("(newArticle: Article { title: newArticleTitle } )")
.Merge("(newArticle)< -[:REFERENCES { count: count }]-(linkedFromArticle)")
.ExecuteWithoutResultsAsync();
}
Unfortunately this adds relationships between all of the new nodes with all of the relationship counts. How do I pair up the two lists with items that have the same index?
I wrote a Cypher query that solve the problem using the range() function and FOREACH.
First, I created an :Article
node with:
CREATE (:Article {title : 'Article A'})
After it, I configured the Neo4j Browser parameters with:
:params { linkedFromArticle : 'Article A', newArticleTitles : ['Article B', 'Article C', 'Article D'], count : [10, 20, 30] }
Then, the Cypher query:
MATCH (linkedFromArticle:Article)
WHERE linkedFromArticle.title = {linkedFromArticle}
WITH linkedFromArticle, RANGE(0, SIZE({count}) - 1) AS indexes
FOREACH(index IN indexes |
MERGE (newArticle:Article { title: {newArticleTitles}[index] } )
MERGE (newArticle)-[:REFERENCES {count : {count}[index]}]->(linkedFromArticle)
)
The resultant graph:
EDIT:
The equivalent C# function using Neo4jClient:
public async Task AddArticlesWithRelationshipsAsync(List<string> newArticleTitles, string linkedFromArticle, List<int> count) {
await client
.Cypher
.WithParam("newArticleTitles", newArticleTitles)
.WithParam("linkedFromArticle", linkedFromArticle)
.WithParam("count", count)
.Match("(linkedFromArticle:Article)")
.Where("linkedFromArticle.title = {linkedFromArticle}")
.With("linkedFromArticle, RANGE(0, SIZE({count}) - 1) AS indexes")
.ForEach("(index IN indexes | " +
"MERGE (newArticle:Article { title: {newArticleTitles}[index] } )" +
"MERGE (newArticle)-[:REFERENCES {count : {count}[index]}]->(linkedFromArticle)" +
")")
.ExecuteWithoutResultsAsync();
}