Skip to content

Latest commit

 

History

History
243 lines (178 loc) · 6.05 KB

README.md

File metadata and controls

243 lines (178 loc) · 6.05 KB

Chirp - simple social media platform

A simple social media platform, written in Scala with graph database system.

Authors

Technologies

  • Database: Neo4J
  • Backend: Scala

Vision statement

Social media platform based on Twitter. Main functionality is ment to be adding, displaying posts and interactions between them. Users will be able to tag, comment or react to posts. Their posts recommendations will be based on followed tags/users.

User stories

As a user I want to add posts in order to tell the world sth.
As a user I want to add tags to created posts in order to specify the target group.
As a user I want to react to posts in order to show my attitude to them.
As a user I want to comment on posts in order to start/participate in meaningful discussions.
As a user I want to react to comments in order to show my attitude to them.
As a user I want to follow other users in order to have their posts recommended.
As a user I want to follow tags in order to have suitable posts recommended.
As a user I want to modify profile info such as bio or photo in order to express myself.
As a user I want to share posts in order to show them to my followers.

Database schema

Schema

image

Relations

image

Backend schema

Initial schema

image

Due to lack of support for scala in Neo4j drivers (there is only one available unofficial driver, that is under development), we changed our schema to:

Final schema

image

Recommendation system

Thanks to using graph database, we could easily retrieve most suitable tags and posts.

We rank posts based on:

  1. Their invidual reaction engagement score, based on number of rections image
  2. User own preferences score:
  • Follow users score: posts created and shared by followed users - collaborative filtering image
  • Subscribed tags score: posts tagged with subscribed tags - content-based filtering image
  1. Post proximity: image

Most used tags query

MATCH (post:POST)-[r:TAGGED]->(tag:TAG) RETURN tag, count(r) ORDER BY count(r) DESC LIMIT 10;

Followed users posts

MATCH (follower:USER {name:userName})-[:FOLLOW]->(followed:USER)-[:CREATED]->(post:POST) RETURN post;

Subscribed tags posts

MATCH (user:USER {name:userName})-[:SUBSCRIBE]->(tag:TAG)<-[:TAGGED]-(post:POST) RETURN post;

Post reactions

MATCH (user:USER)-[r:REACTED_TO]->(post:POST) WHERE ID(post)=postId RETURN count(r);

Post proximity query

MATCH (user:USER {name:userName}), (post:POST), path = shortestPath((user)-[*]-(post))
WITH path, post 
WHERE length(path) <= maxDistance
RETURN post

Commonly followed query

MATCH (they:USER {name:userName1})-[r:FOLLOW]->(common:USER)
WITH common
MATCH(me:USER {name:userName2})-[r: FOLLOW]->(common:USER)
RETURN common

Also followe by query

MATCH (me:USER {name:myUserName})-[r:FOLLOW]->(them:USER)
WITH them
MATCH (them:USER)-[r: FOLLOW]->(checked:USER {name:checkedUserName})
RETURN them

Backend endpoints

We created a few endpoints, that allow to:

  1. Login user / create new if doesn't exits
  @cask.post("/login")
  def login(userName: String)
  1. Create post
  @cask.post("/post/create")
  def createPost(userName: String, postContent: String, tags: String)
  1. Comment on post
  @cask.post("/post/comment")
  def createComment(userName: String, commentContent: String, tags: String, postId: String)
  1. Get post comments
  @cask.get("/post/comments")
  def getComments(postId: String)
  1. React to post
  @cask.post("/post/react")
  def react(userName: String, postId: String, reactionType: String)
  1. Share post
  @cask.post("/post/share")
  def share(userName: String, postId: String)
  1. Delete post
  @cask.post("/post/delete")
  def deletePost(postId: String)
  1. Update post
  @cask.post("/post/update")
  def updatePost(userName: String, postId: String, postContent: String)
  1. Subscribe tag
  @cask.post("/tag/subscribe")
  def subscribe(userName: String, tagName: String)
  1. Get recommended tags
  @cask.get("tag/recommended")
  def recommendedTags()
  1. Follow user
  @cask.post("/users/follow")
  def followUser(followerUserName: String, followedUserName: String)
  1. Get posts recommended for user
  @cask.get("/users/recommendedPosts")
  def recommendedPosts(userName: String)
  1. Update bio
  @cask.post("/users/updateBio")
  def updateBio(userName: String, bio: String)
  1. Get profiles followed by user
  @cask.get("/users/followed")
  def followed(userName: String)
  1. Get profiles following user
  @cask.get("/users/followers")
  def followers(userName: String)
  1. Get profiles followed commonly by two users
  @cask.get("/users/commonFollowed")
  def commonFollowed(userName1: String, userName2: String)
  1. Get profiles also following certain user
  @cask.get("/users/alsoFollowedBy")
  def alsoFollowedBy(myUserName: String, checkedUserName: String)

Example returns

  1. Recommended posts: image

  2. Recommended tags: image

Frontend

Unfortunately, we haven't finished our frontend/backend integration. We have only created mock frontend without calls to Scala backend.

Here is quick look of how our feed page would look like.

image