A simple social media platform, written in Scala with graph database system.
- Database: Neo4J
- Backend: Scala
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.
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.
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:
Thanks to using graph database, we could easily retrieve most suitable tags and posts.
We rank posts based on:
- Follow users score: posts created and shared by followed users - collaborative filtering
- Subscribed tags score: posts tagged with subscribed tags - content-based filtering
MATCH (post:POST)-[r:TAGGED]->(tag:TAG) RETURN tag, count(r) ORDER BY count(r) DESC LIMIT 10;
MATCH (follower:USER {name:userName})-[:FOLLOW]->(followed:USER)-[:CREATED]->(post:POST) RETURN post;
MATCH (user:USER {name:userName})-[:SUBSCRIBE]->(tag:TAG)<-[:TAGGED]-(post:POST) RETURN post;
MATCH (user:USER)-[r:REACTED_TO]->(post:POST) WHERE ID(post)=postId RETURN count(r);
MATCH (user:USER {name:userName}), (post:POST), path = shortestPath((user)-[*]-(post))
WITH path, post
WHERE length(path) <= maxDistance
RETURN post
MATCH (they:USER {name:userName1})-[r:FOLLOW]->(common:USER)
WITH common
MATCH(me:USER {name:userName2})-[r: FOLLOW]->(common:USER)
RETURN common
MATCH (me:USER {name:myUserName})-[r:FOLLOW]->(them:USER)
WITH them
MATCH (them:USER)-[r: FOLLOW]->(checked:USER {name:checkedUserName})
RETURN them
We created a few endpoints, that allow to:
- Login user / create new if doesn't exits
@cask.post("/login")
def login(userName: String)
- Create post
@cask.post("/post/create")
def createPost(userName: String, postContent: String, tags: String)
- Comment on post
@cask.post("/post/comment")
def createComment(userName: String, commentContent: String, tags: String, postId: String)
- Get post comments
@cask.get("/post/comments")
def getComments(postId: String)
- React to post
@cask.post("/post/react")
def react(userName: String, postId: String, reactionType: String)
- Share post
@cask.post("/post/share")
def share(userName: String, postId: String)
- Delete post
@cask.post("/post/delete")
def deletePost(postId: String)
- Update post
@cask.post("/post/update")
def updatePost(userName: String, postId: String, postContent: String)
- Subscribe tag
@cask.post("/tag/subscribe")
def subscribe(userName: String, tagName: String)
- Get recommended tags
@cask.get("tag/recommended")
def recommendedTags()
- Follow user
@cask.post("/users/follow")
def followUser(followerUserName: String, followedUserName: String)
- Get posts recommended for user
@cask.get("/users/recommendedPosts")
def recommendedPosts(userName: String)
- Update bio
@cask.post("/users/updateBio")
def updateBio(userName: String, bio: String)
- Get profiles followed by user
@cask.get("/users/followed")
def followed(userName: String)
- Get profiles following user
@cask.get("/users/followers")
def followers(userName: String)
- Get profiles followed commonly by two users
@cask.get("/users/commonFollowed")
def commonFollowed(userName1: String, userName2: String)
- Get profiles also following certain user
@cask.get("/users/alsoFollowedBy")
def alsoFollowedBy(myUserName: String, checkedUserName: String)
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.