Reputation: 3
I am attempting to create a user rating system through the use of Neo4j and was hoping y'all could lend some advice. The way I originally thought to approach this is through relating the user to a StarRate node. In this node I was to have properties of relating property id, as well as a property for each of the 5 stars in the rating system. For every rating they are given (1-5 stars) I will increment said star's property.
My question is, with this approach, how should I go about collecting the overall star rating? Feel free to drop some ideas or places I could tweak my implementation. Thanks
Upvotes: 0
Views: 84
Reputation: 767
At the end of the day, it depends on which extra uses you are going to need. Anyway you will need a variable votesAmount for the amount of votes received and totalStars for the sum of all stars, so you can get total rating while being easy to update it. I´ll drop some extra examples:
1) If you want to know, or think you will want to know in the future, who rated whom, then I would suggest creating for each rating:
(user:User)-[rates{rating:3}:RATES]->(otherUser:User)
This extra information could be used to track active users, toxic users, etc. Here the math would be:
MATCH (user:User{name:'user1'})
OPTIONAL MATCH (user)<-[rates:RATES]-(:User)
WITH count(rates) AS totalVotes, sum(rates.rating) AS totalStars
2) If just want to know the average rating of an User, then I would have:
(user:User)-[:HAS_RATING]->(rating{totalStars=16, votesAmount=4})
This makes it easy to get the average rating of an User directly from its node while it´s also easy to add a new rating (add stars to totalStars, add 1 to votesAmount). It´s the same as your idea, but with less information (no stars breakdown) in case you don´t want to use it.
With your original implementation, the total rating for an user it would be:
MATCH (user:User{name:'user1'})-[:HAS_RATING]->(rating:Rating)
WITH rating.stars1 + rating.stars2 + rating.stars3 + rating.stars4 + rating.stars5 as votesAmount,
rating.stars1 * 1 + rating.stars2 * 2 + rating.stars3 * 3 + rating.stars4 * 4 + rating.stars5 * 5 as totalStars
And in any implementation I would finish with
RETURN totalStars/votesAmount AS totalRating
Upvotes: 0
Reputation: 66999
Instead of creating a rating node (and a relationship) for each user, it would be much simpler if you just had a rating property in each user node.
Upvotes: 1