Reputation: 65
I have an MVC Asp.Net application that is connected to a Neo4j database. In my database there is a relationship (m:Movie)<-[r:HAS_WATCHED_MOVIE]-(u:User)
between movie
and user
entities.
What I want to do is return a IEnumerable<Movie>
that contains top 3 movies (top movies are the movies with most HAS_WATCHED_MOVIE
relationsips) in descending order.
I have already figured out a Cypher query to do this, and it goes like this:
MATCH (m:Movie)<-[r:HAS_WATCHED_MOVIE]-(b)
RETURN m, COUNT(r)
ORDER BY COUNT(r) DESC
LIMIT 3
Since I'm new with Neo4j C# client, I'm not sure how to go about writing this query in c#?
Upvotes: 0
Views: 3038
Reputation: 6270
var client = new BoltGraphClient("bolt://localhost:7687", "neo4j", "neo");
client.Connect();
var query = client.Cypher
.Match("(m:Movie)<-[r:HAS_WATCHED_MOVIE]-(b)")
.Return((m,r) => new {
Movie = m.As<Movie>(),
Count = r.Count()
})
.OrderByDescending("Count")
.Limit(3);;
foreach(var result in query.Results)
Console.WriteLine($"'{result.Movie.Title}' had {result.Count} watchers");
For this one, I have my Movie
class defined as:
public class Movie{
[JsonProperty("title")]
public string Title {get;set;}
}
using (var driver = GraphDatabase.Driver("bolt://localhost:7687", AuthTokens.Basic("neo4j", "neo")))
{
using (var session = driver.Session())
{
using (var tx = session.BeginTransaction())
{
IStatementResult results = tx.Run(
@"MATCH (m:Movie)<-[r:HAS_WATCHED_MOVIE]-(b)
RETURN m, COUNT(r)
ORDER BY COUNT(r) DESC
LIMIT 3");
foreach (IRecord result in results)
{
var node = result["m"].As<INode>();
var title = node.Properties["title"]?.As<string>();
var count = result["COUNT(r)"].As<long>();
var movie = new Movie {
Title = title,
};
Console.WriteLine($"'{movie.Title}' had {count} watchers");
}
}
}
}
NB. I've only done the new Movie
bit in this one, as you say you wanted an IEnumerable<Movie>
response.
The Neo4jClient
one doesn't return an IEnumerable<Movie>
as you're using the COUNT
call in the RETURN
you'd need to do something like:
var query = gc.Cypher
.Match("(m:Movie)<-[r:HAS_WATCHED_MOVIE]-(b)")
.With("m, COUNT(r) AS count")
.Return((m, r) => m.As<Movie>())
.OrderByDescending("count")
.Limit(3);
Where you use a WITH
to do the COUNT
before returning. You don't have to do this with the Neo4j-Driver
version as you can fake it after the fact, but I would still change the query if all you want is the Movie
to:
IStatementResult results = tx.Run(
@"MATCH (m:Movie)<-[r:HAS_WATCHED_MOVIE]-(b)
WITH m, COUNT(r) AS count
RETURN m
ORDER BY count DESC
LIMIT 3");
Upvotes: 5