Difference between revisions of "Social Network Matchmaking"
Orrbradford (talk | contribs) |
m (Protected "Social Network Matchmaking" ([Edit=Allow only administrators] (indefinite) [Move=Allow only administrators] (indefinite))) |
||
(16 intermediate revisions by one other user not shown) | |||
Line 7: | Line 7: | ||
[https://github.com/ESE205/social-network-matchmaking Github Repo] | [https://github.com/ESE205/social-network-matchmaking Github Repo] | ||
+ | |||
+ | [https://classes.engineering.wustl.edu/ese205/core/index.php?title=Android_API_Calls_With_Retrofit#Let.27s_Get_Started Tutorial] | ||
+ | |||
+ | [https://drive.google.com/file/d/1EwWjwNO2slhOU-qC-08rOBPskK2XQkWC/view?usp=sharing Poster] | ||
==Project Proposal== | ==Project Proposal== | ||
Line 58: | Line 62: | ||
== Design and Solutions == | == Design and Solutions == | ||
+ | |||
+ | Because this is an android application the actual design of the app hinged on how I decided to house features in the User Interface and how those features could communicate with each and be traversed. After studying some other similar apps this is this design wireframe I went with: | ||
+ | |||
+ | [[File:snmfinalappflow.png | 400px]] | ||
===Registration and Login=== | ===Registration and Login=== | ||
Line 63: | Line 71: | ||
The first step of creating the app was implementing user authentication and account creation. This feature was a good starting point because it allowed me to become familiar with building Android UI and working with activities. The backend of this feature was implemented using Firebase. Google Firebase has an authentication module that produces a unique user id and handles user authentication and login. Using it in the app was as easy as importing the approbate libraries and learning to use the Firebase api. | The first step of creating the app was implementing user authentication and account creation. This feature was a good starting point because it allowed me to become familiar with building Android UI and working with activities. The backend of this feature was implemented using Firebase. Google Firebase has an authentication module that produces a unique user id and handles user authentication and login. Using it in the app was as easy as importing the approbate libraries and learning to use the Firebase api. | ||
− | On the front end I built a registration page and login page in Android studio using XML and Java. At this stage it was very important to to decide exactly what information is important for users to provide. Because this is ultimately a dating app I decided that the most basic information needed included user's names, ages, location, and gender. We also take user input for an email address and password and pass everything along to to the Firebase authentication api. Whenever a user is created, Firebase assigns them a unique ID. This ID is used throughout to ensure unique friend connections and matches. We also add the user to the FirebaseFirestore database. The Firestore database is a NoSQL database that use a nested hierarchy to store information. We use this to store the user's info. We store the majority of user information here because it is less computationally expensive to retrieve that data from this database. When we add a user we also add them to the Neo4J database. The Neo4j database uses a system of nodes and edges to store information about users. Nodes consist of labels and we can also store information within the node. We label our user nodes as Persons and we also label them by their gender. In addition to this we pass along the ID and the names. | + | On the front end I built a registration page and login page in Android studio using XML and Java. At this stage it was very important to to decide exactly what information is important for users to provide. Because this is ultimately a dating app I decided that the most basic information needed included user's names, ages, location, and gender. We also take user input for an email address and password and pass everything along to to the Firebase authentication api. Whenever a user is created, Firebase assigns them a unique ID. This ID is used throughout to ensure unique friend connections and matches. We also add the user to the FirebaseFirestore database. The Firestore database is a NoSQL database that use a nested hierarchy to store information. We use this to store the user's info. We store the majority of user information here because it is less computationally expensive to retrieve that data from this database. When we add a user we also add them to the Neo4J database. The Neo4j database uses a system of nodes and edges to store information about users. Nodes consist of labels and we can also store information within the node. We label our user nodes as Persons and we also label them by their gender. In addition to this we pass along the ID and the names. |
+ | |||
+ | The Neo4j database is much larger and much more computationally extensive than relational databases and because of this we don't want to use it as our primary database. The Neo4j database is also not well suited for certain tasks. Things like chat would not work well in a graph database. These are all things I have to keep in mind. | ||
+ | |||
+ | The creation of the api for the Neo4j database is more intensive than the Firebase API. To access the database from online we have to use a web server and we need to use a server side language to communicate between the API, the app, and the database. To accomplish this we use Amazon AWS EC2 cloud server along with NodeJS and Express. Using express we can create 'routes' that make it very easy to process url requests to our server. We structure these routes based on the three core functionalities we will be using our server for: creating users, handling friending features, and handling matching features. We also install Neo4j in the server. This allows us to make calls to the server from online using ports. This also allows us to use Neo4j's interactive database explorer in the browser. This helps to quickly check the information we are placing in the database. | ||
+ | |||
+ | Schemas: | ||
+ | |||
+ | Neo4j User Nodes | ||
+ | |||
+ | <source> | ||
+ | (Labels: Person, Gender) | ||
+ | "name": <String>, | ||
+ | "id": <String> | ||
+ | </source> | ||
+ | |||
+ | FirebaseFirestore: | ||
+ | |||
+ | <source> | ||
+ | Collection: users | ||
+ | document<user id> | ||
+ | "age":<String> | ||
+ | "city":<String> | ||
+ | "name": <String>, | ||
+ | "gender": <String> | ||
+ | "img_url":<String> | ||
+ | </source> | ||
+ | |||
+ | <gallery widths=250px heights=250px mode=nolines> | ||
+ | File:ctlogin.jpg | Login | ||
+ | File:ctregister.jpg | Register | ||
+ | File:ctprofile.jpg | Profile | ||
+ | </gallery> | ||
===Adding Friends=== | ===Adding Friends=== | ||
− | Adding friends was created in Firebase and Neo4j although we only really use the Neo4j to add the friends. We also created | + | Moving on I next added functionality for the addition of friends for users. This is is crucial to the app because the core functionality involves matching your friends with your other friends. Adding friends was created both in Firebase and Neo4j although we only really use the Neo4j to add the friends. To create friends in Neo4j we break the process into 3 steps. First users have to be able to send friend requests to users, then users have to be able to accept friend request, and finally users need to be able to see a list of their friends. In the UI for the app we break these actions into two tabs. We have one tab listing all friends for the user. The second tab prints a list of all users and allows the user to send a request through a button press. The second tab also list all friend request a user has received and allows for acceptance or denial. In our backend we handle the friend requests by creating an edge in between nodes. We pull all nodes connected by a friend request edge of the user to get the list of friend request. Upon acceptance of a request, we destroy this request edge and replace it with a friend edge. |
+ | |||
+ | We also created a friend list in FirebaseFireStore because we wanted to reduce the amount of queries that we sent to the Neo4j server. By having the list in Firebase we can easily pull a list of friends from there. Especially as the number of friends grows, this would make it easier to process this request. | ||
+ | |||
+ | Schemas: | ||
+ | |||
+ | Neo4j Friend Edges | ||
+ | |||
+ | <source> | ||
+ | friendRequest - one directional edge between two Persons | ||
+ | friends - bidirectional edge between two Persons | ||
+ | notfriends - bidirectional edge between two Persons | ||
+ | </source> | ||
+ | |||
+ | FirebaseFirestore: | ||
+ | |||
+ | <source> | ||
+ | Collection: friends | ||
+ | document<user id> | ||
+ | <id>:<name> | ||
+ | </source> | ||
+ | |||
+ | <gallery widths=250px heights=250px mode=nolines> | ||
+ | File:Neo4j3.png | | ||
+ | File:Neo4j4.png | | ||
+ | File:ctfriendadd.jpg | | ||
+ | </gallery> | ||
===Matching=== | ===Matching=== | ||
− | For Matching we used Neo4j. | + | For Matching we used Neo4j. Matching worked similarly as the friending concept except that instead of a user directly sending a request, a friend of the two users would do it. This broke our process up for matching into the following:friend of users must match users, both users must accept, chat functionality must be enabled between matched users. This is also created a unique issue in that we want to be able to keep track of exactly who has endorsed a match. To accomplish all of this I incorporated the use of a "match node". Using this match node I would keep track of who had been matched within the node and use edges to the node to denote whether someone endorsed the connection or not. This also made it easier in terms of retrieval. Getting the number of endorsers was as easy as counting connections to the match node. Deciding when a match had been successfully completed required me to evaluate 2 states: Either both had accepted or one user had rejected the pairing. I didn't want to evaluate this everytime I pulled information from Neo4j so I also created a "Match Complete" node that every node would point to when it was complete. Users would only be shown matches that were still open and upon acceptance they would either accept the match which changed the edge to node or they would complete the match which would also create an edge to the Match Complete node and open chat functionality if applicable. |
+ | |||
+ | Schemas: | ||
+ | |||
+ | Neo4j Match Nodes and Edges | ||
+ | |||
+ | <source> | ||
+ | Match Node | ||
+ | (Labels: match) | ||
+ | "femaleId":<string> | ||
+ | "maleId":<string> | ||
+ | "femaleName":<string> | ||
+ | "maleName":<string> | ||
+ | |||
+ | Match Complete Node | ||
+ | (Labels: matchComplete) | ||
+ | |||
+ | Edges | ||
+ | endorse - edge pointing from Person node to match node. Has parameters of "type":<string> | ||
+ | matchedWith - edge pointing from Person node to match node. Has parameters of "status":<string> | ||
+ | matchComplete - edge pointing from match node to matchComplete node | ||
+ | |||
+ | </source> | ||
+ | |||
+ | <gallery widths=250px heights=250px mode=nolines> | ||
+ | File:Neo4j6.png | | ||
+ | File:Neo4j7.png | | ||
+ | File:ctpair.jpg | | ||
+ | </gallery> | ||
+ | |||
===Chatting=== | ===Chatting=== | ||
− | + | I implemented the chat feature using Firebase Realtime Database. Firebase Realtime Database differed from the FirebaseFirestore in that it is real time and also follows a different NoSQL structure. It is still just a nested hierarchy of information however. I designed the UI so that users would see a list of individuals to chat with. Upon selecting an individual they would be shifted to a chat room where they could message one another. Using the realtime database allowed for realtime updates. I created the backend using a heiracrhcy of chatrooms. Each chatroom was given a unique ID. I created a list of chat room IDs alongside user information in Firebase Firestore to keep track of who they were allowed to chat with. I used this list to populate the UI list. Inside the chat room heiracrhcy chats are ordered by a sequential key that increments every time a new chat is made. I keep track of which user sent the message and the contents of the message. | |
+ | |||
+ | Firebase Database Chat Schema | ||
+ | |||
+ | Chat | ||
+ | |||
+ | Chat ID <Int> | ||
+ | Message Number <Int> | ||
+ | "ID": <String> | ||
+ | "Name":<String> | ||
+ | "Message":<String> | ||
+ | |||
+ | |||
+ | |||
+ | <gallery widths=250px heights=250px mode=nolines> | ||
+ | File:ctchat.jpg | | ||
+ | </gallery> | ||
+ | |||
== Results == | == Results == | ||
− | + | Ultimately the main functions of the app were completed. | |
+ | |||
+ | However due to time constraints the app has several issues. | ||
+ | |||
+ | ===UI/UX=== | ||
+ | The UI is terrible and bland and rife with tiny errors that can make it a nightmare to use. For example I didn't have time to implement notifications for every action that a user takes. So a user might hit a button a some action will happen on the backend but the user will not be alerted to this. In many places the UI will also not shift properly which is very important from a user perspective. After testing with different devices, I also noticed that it doesn't scale properly to different screen sizes | ||
+ | |||
+ | The app is also just not very fun to use at all. I can chalk this up to the core functionality of the app being too bare on its own to elicit excitement from users. I realize after building it that the UX is very important in keeping users engaged and actually creating a product that depends on having users use it for the purpose to actually make sense. Looking at similar apps such as Tinder, Bumble, or OKCupid, I realize they have certain ways they gamify the process to make it more enjoyable to users. My app has none of this and I think it is a crucial element. | ||
+ | |||
+ | ===Databases=== | ||
+ | |||
+ | Over the course of building this app I ended up using three different databases which present it's own set of unique challenges. All of the databases have different loads restraints and different structures. While each was useful on its own for specific functionality, it was a nightmare to actually learn how to use them all and have to restructure my data uniquely for each database. Each database also had severe limitations that were at times very difficult to get through. In terms of moving data in between sources, it is time consuming to develop three different injection methods for three different databases. | ||
+ | |||
+ | ===Neo4j scaling issues=== | ||
+ | |||
+ | Neo4j turned out to be great at graph functionality but the size of it ultimately turned me off to using it in the future. This was partially because I was using a free version of Neo4j on a free Tier service of Amazon AWS. Neo4j frequently reminded me that it did not have the standards it wanted to have maximum capability. To put this in perspective, Neo4j requested 8 GB of ram at a minimum and the ability to use 40,000 reads and writes simultaneously. My Amazon AWS server had 2GB of ram and I gave Neo4j about 1024 reads/writes. This produced a sense of dread in me whenever I used the database because I feared I would put too much data inside it of and it grow large enough that Amazon would begin charging me money. The actual cost of running a "real" Neo4j server was outside the realm of my pockets. If I was to turn this into a production app, I don't think that I would use Neo4j at all. | ||
+ | |||
+ | Neo4j's cypher language was very intuitive and easy to use. Although I didn't have the time to get to the actual fun tasks of using graph algorithms to create better matches, the path to do so was clearly laid out. In the future I think Neo4j would be a great way of quickly testing algorithms, but I would use a different database with much less scaling costs that could implement some of the graphing functionality I needed. | ||
+ | |||
+ | ===Lack of Analytical Components=== | ||
+ | |||
+ | A big draw for building this app was to implement network algorithms on social network data to provide high quality match suggestions to users. It never quite reached this point due to time constraints. The app in it's current form does not use any special techniques to develop the matching queue between users. This is a major area of improvement. | ||
==Next Steps== | ==Next Steps== | ||
− | + | *Improve UI - make the app more visually pleasing | |
+ | *Incorporate algorithms in deterring matching queues | ||
+ | *Add gamification to the app to improve the user experience - Keep track of how many successful matches users have, add a score system, etc. | ||
+ | *Switch away from Neo4j - Neo4j is great but switching to another database would make it much easier to scale and eventually launch as a product | ||
+ | |||
+ | ==Poster== | ||
+ | |||
+ | [[File:snmfinalposter.png | 400px]] | ||
==References== | ==References== | ||
− | + | I used a great amount of references while learning how to develop in android. If I directly copied code this is noted in my code in Github. | |
+ | |||
+ | *[https://medium.com/octavian-ai/review-prediction-with-neo4j-and-tensorflow-1cd33996632a Review prediction with Neo4j and TensorFlow – Octavian – Medium] | ||
+ | *[https://medium.com/labcodes/graph-databases-talking-about-your-data-relationships-with-python-b438c689dc89 Graph Databases: Talking about your Data Relationships with Python] | ||
+ | *[https://medium.com/@srinuraop/sending-messages-from-app-server-to-clients-using-fcm-b2a471fc3e33 Sending Messages from App Server to Clients Using FCM] | ||
+ | *[https://www.raywenderlich.com/5359-firebase-tutorial-real-time-chat Firebase Tutorial: Real-time Chat | raywenderlich.com] | ||
+ | *[https://www.quora.com/What-is-Facebooks-architecture-6?redirected_qid=141492 (1) What is Facebook's architecture? - Quora] | ||
+ | *[https://www.quora.com/How-does-Facebook-maintain-a-list-of-friends-for-each-user-Does-it-maintain-a-separate-table-for-each-user How does Facebook maintain a list of friends for each user? Does it maintain a separate table for each user? - Quora] | ||
+ | *[https://www.quora.com/I-want-to-implement-a-database-with-my-Android-app-that-incorporates-a-User-Registration-feature-Users-will-be-able-to-create-friends-lists-and-I%E2%80%99ll-store-the-user-information-pictures-and-listings-Will-NOSQL-DB-or-a-relational-DB-be-better I want to implement a database with my Android app that incorporates a User Registration feature. Users will be able to create friends lists, and I’ll store the user information, pictures, and listings. Will NOSQL DB or a relational DB be better? - Quora] | ||
+ | *[https://stackoverflow.com/questions/46554091/firebase-firestore-collection-count Firebase firestore collection count - Stack Overflow] | ||
+ | *[https://code.tutsplus.com/tutorials/how-to-code-a-bottom-navigation-bar-for-an-android-app--cms-30305 How to Code a Bottom Navigation Bar for an Android App] | ||
+ | *[https://developer.android.com/training/basics/fragments/communicating.html Communicate with other fragments | Android Developers] | ||
+ | *[https://stackoverflow.com/questions/42362917/fragment-re-created-on-bottom-navigation-view-item-selected android - Fragment re-created on bottom navigation view item selected - Stack Overflow] | ||
+ | *[https://medium.com/@avinriyan/android-kotlin-bottom-navigation-tab-layout-19d062256882 Android Kotlin: Bottom Navigation + Tab Layout – Avin Riyan – Medium] | ||
+ | *[https://medium.com/@droidbyme/android-material-design-tabs-tab-layout-with-swipe-884085ae80ff Android Material Design Tabs (Tab Layout) with Swipe] | ||
+ | *[https://github.com/mitchtabian/TabFragments mitchtabian/TabFragments: How to use Tabs in Android Application] | ||
+ | *[https://www.youtube.com/watch?v=bNpWGI_hGGg Android Tab Tutorial (Android Studio Tab Fragments) - YouTube] | ||
+ | *[https://github.com/mitchtabian/NavigateWithFragmentsTutorial2 mitchtabian/NavigateWithFragmentsTutorial2: Learn how to use the navigation bar and fragments!] | ||
+ | *[https://stackoverflow.com/questions/24502394/call-a-fragment-method-from-an-adapter java - Call a Fragment method from an Adapter - Stack Overflow] | ||
+ | *[https://stackoverflow.com/questions/15444375/how-to-create-interface-between-fragment-and-adapter java - How to create interface between Fragment and adapter? - Stack Overflow] | ||
+ | *[https://stackoverflow.com/questions/10514473/string-to-hashmap-java dictionary - String to HashMap JAVA - Stack Overflow] | ||
+ | *[https://stackoverflow.com/questions/20000018/set-viewpager-height-inside-scrollview-in-android Set Viewpager height inside Scrollview in android - Stack Overflow] | ||
+ | *[https://www.kankan968.xyz/a/73.html Android NestedScrollView/ScrollView wrapping ViewPager adaptive height | kankan968] | ||
+ | *[https://hackernoon.com/how-to-develop-a-boilerplate-for-api-with-node-js-express-and-mongodb-4c771ae1c2df How to Develop a Boilerplate for API with Node.js, Express, and MongoDB] | ||
+ | *[https://stackoverflow.com/questions/23450534/how-to-call-a-python-function-from-node-js How to call a Python function from Node.js - Stack Overflow] | ||
+ | *[https://maxdemarzi.com/ Max De Marzi | Graphs with Neo4j] | ||
+ | *[https://dzone.com/articles/installing-java-8-on-aws-ec2-amazon-linux-instance Installing Java 8 on AWS EC2 Amazon Linux Instance - DZone Cloud] | ||
+ | *[https://java.com/en/download/linux_manual.jsp Download Java for Linux] | ||
+ | *[https://linuxize.com/post/install-java-on-centos-7/ How to install Java on CentOS 7 | Linuxize] | ||
+ | *[https://stackoverflow.com/questions/41110305/connecting-to-neo4j-on-ec2 amazon ec2 - Connecting to neo4j on ec2 - Stack Overflow] | ||
+ | *[https://hackernoon.com/tutorial-creating-and-managing-a-node-js-server-on-aws-part-1-d67367ac5171 Tutorial: Creating and managing a Node.js server on AWS, part 1] | ||
+ | *[https://neo4j.com/developer/javascript/ Neo4j from JavaScript - Neo4j Graph Database Platform] | ||
+ | *[https://gist.github.com/subfuzion/08c5d85437d5d4f00e58 curl POST examples] | ||
+ | *[https://medium.com/@prakash_pun/retrofit-a-simple-android-tutorial-48437e4e5a23 Retrofit— A simple Android tutorial – Prakash Pun – Medium] | ||
+ | *[https://maxdemarzi.com/2018/07/12/building-a-dating-site-with-neo4j-part-two/ Building a Dating site with Neo4j – Part Two | Max De Marzi] | ||
+ | *[https://github.com/maxdemarzi/dating_site maxdemarzi/dating_site: Example Dating Site with Neo4j] | ||
+ | *[https://linkurio.us/blog/using-neo4j-to-build-a-recommendation-engine-based-on-collaborative-filtering/ Using Neo4j to build a recommendation engine based on collaborative filtering - Linkurious] | ||
+ | *[https://blog.sendbird.com/android-chat-tutorial-building-a-messaging-ui Android Chat Tutorial: Building a Messaging UI | SendBird Blog] | ||
+ | *[https://stackoverflow.com/questions/32514410/logging-with-retrofit-2 java - Logging with Retrofit 2 - Stack Overflow] | ||
+ | *[https://www.simplifiedcoding.net/bottom-navigation-android-example/ Bottom Navigation Android Example using Fragments] | ||
+ | *[https://constraintlayout.com/basics/create_chains.html ConstraintLayout] | ||
+ | *[https://developer.android.com/reference/android/support/constraint/ConstraintLayout ConstraintLayout | Android Developers] | ||
+ | *[https://firebase.google.com/docs/guides/ Firebase Guides | Firebase] | ||
+ | *[https://github.com/bumptech/glide bumptech/glide: An image loading and caching library for Android focused on smooth scrolling] | ||
+ | *[https://medium.com/@impaachu/how-to-upload-data-to-firebase-firestore-cloud-database-63543d7b34c5 How to upload data to Firebase Firestore Cloud Database] | ||
+ | *[https://code.tutsplus.com/tutorials/how-to-code-a-bottom-navigation-bar-for-an-android-app--cms-30305 How to Code a Bottom Navigation Bar for an Android App] | ||
+ | *[https://stackoverflow.com/questions/8597769/when-and-why-should-i-use-fragments-in-android-applications When and why should I use fragments in Android applications? - Stack Overflow] | ||
+ | *[https://stackoverflow.com/questions/20306091/dilemma-when-to-use-fragments-vs-activities android - Dilemma: when to use Fragments vs Activities: - Stack Overflow] | ||
+ | *[https://stackoverflow.com/questions/28684759/import-material-design-icons-into-an-android-project Import material design icons into an android project - Stack Overflow] | ||
+ | *[https://www.simplifiedcoding.net/bottom-navigation-android-example/ Bottom Navigation Android Example using Fragments] | ||
+ | *[https://developer.android.com/training/basics/fragments/communicating.html Communicate with other fragments | Android Developers] | ||
+ | *[https://medium.com/@droidbyme/android-material-design-tabs-tab-layout-with-swipe-884085ae80ff Android Material Design Tabs (Tab Layout) with Swipe] | ||
+ | |||
+ | |||
[[Category:Projects]] | [[Category:Projects]] | ||
[[Category:Spring 2019 Projects]] | [[Category:Spring 2019 Projects]] |
Latest revision as of 11:51, 2 May 2019
The Social Network Matchmaking App will be an android application that will allow users to promote matchmaking within their social networks. The app will be created using Java, Google Firebase, NodeJS, and Neo4j.
Contents
Links
Social Network Matchmaking Log
Project Proposal
Background
Online matchmaking has become much more popular in recent years driven by the popularity of online services such as Tinder and Match.com. Most of these apps operate on exposing you to as many people as possible whether that is through geolocation (Tinder, Bumble, etc.) or preferences (Match.com, EHarmony). The central idea behind the Social Network Matchmaking app is to connect individuals to others within their own social networks. Ideally their would be a few crucial benefits to this such as self moderated behavior and better thought out matches.
A common complaint for women in online dating apps is that men will send unwanted crass or explicit messages. Ideally this behavior could be reduced by removing anonymity from the process. For every person that is connected, they are aware that their behavior might be relayed back to their social network.
Another complaint of apps that are based on generating many matches is that the value of an individual match is extremely low. Ideally people that know both people will be able to give a more informed assessment which will lead to better matches, better conversations, and ultimately better relationships.
App Features
The planned app will contain two main features: connect with people you know and matching people in your network together.
Connecting with people in Network
Users can search for their friends and send friend requests to them.
Matching people in your network
Users will be able to match their 1st degree connections with other 1st degree connections in their network. When users do this, both of the matched persons will be alerted that someone has matched them together. As more people match them together, they can see that more people believe they would be a good match. Users that have been matched can also at anytime signal that they want to chat with the person they were match with and if both people accept then a chat will be opened between them.
Development
The app will be develop for the android using a combination of Java, Firebase, NodeJS, and Neo4j.
Java
Java is the primary language used to develop android applications. Also considered was the language Kotlin but the decision was ulimtately made to go with Java as I am more familiar with Java and want to prioritize time towards building the backend.
Firebase
Firebase is a Backend As a Service (BaaS) offered by google. Using firebase will for easy implementation of authentication and database service. Many features of the app such as signing up and maintaining friends list will be handled by Firebase and allow for more time to be devoted to implementing the core features of the app. Firebase uses a NoSql structure. The entire backend could be placed on Firebase but given the complexity of a social network structure and the exponential increase as it gets larger, another database will be used to supplement firebase.
NodeJS
NodeJS and Express will be used as the backend web server and to build the API logic. NodeJS was chosen due to the past experience using it and because of the great support it has for Neo4j.
Neo4j
Neo4j is a graph based database. Neo4j was chosen as the primary database because it was developed with graphs in mind unlike relational databases and has key core functionality built in that will allow for easier implementation of features. It was also chosen because I have no experience using graph databases and I believe that this experience should be a learning one. As I'm unfamiliar with Neo4j, some time will be needed to evaluate the full list of features and ensure that it is possible. Something that should be completed by the final proposal deadline.
Budget
The anticipated budget for this project is 0$. This might change if free tier hosting limits in Amazon AWS or Firebase are exceeded.
Gantt Chart
Design and Solutions
Because this is an android application the actual design of the app hinged on how I decided to house features in the User Interface and how those features could communicate with each and be traversed. After studying some other similar apps this is this design wireframe I went with:
Registration and Login
The first step of creating the app was implementing user authentication and account creation. This feature was a good starting point because it allowed me to become familiar with building Android UI and working with activities. The backend of this feature was implemented using Firebase. Google Firebase has an authentication module that produces a unique user id and handles user authentication and login. Using it in the app was as easy as importing the approbate libraries and learning to use the Firebase api.
On the front end I built a registration page and login page in Android studio using XML and Java. At this stage it was very important to to decide exactly what information is important for users to provide. Because this is ultimately a dating app I decided that the most basic information needed included user's names, ages, location, and gender. We also take user input for an email address and password and pass everything along to to the Firebase authentication api. Whenever a user is created, Firebase assigns them a unique ID. This ID is used throughout to ensure unique friend connections and matches. We also add the user to the FirebaseFirestore database. The Firestore database is a NoSQL database that use a nested hierarchy to store information. We use this to store the user's info. We store the majority of user information here because it is less computationally expensive to retrieve that data from this database. When we add a user we also add them to the Neo4J database. The Neo4j database uses a system of nodes and edges to store information about users. Nodes consist of labels and we can also store information within the node. We label our user nodes as Persons and we also label them by their gender. In addition to this we pass along the ID and the names.
The Neo4j database is much larger and much more computationally extensive than relational databases and because of this we don't want to use it as our primary database. The Neo4j database is also not well suited for certain tasks. Things like chat would not work well in a graph database. These are all things I have to keep in mind.
The creation of the api for the Neo4j database is more intensive than the Firebase API. To access the database from online we have to use a web server and we need to use a server side language to communicate between the API, the app, and the database. To accomplish this we use Amazon AWS EC2 cloud server along with NodeJS and Express. Using express we can create 'routes' that make it very easy to process url requests to our server. We structure these routes based on the three core functionalities we will be using our server for: creating users, handling friending features, and handling matching features. We also install Neo4j in the server. This allows us to make calls to the server from online using ports. This also allows us to use Neo4j's interactive database explorer in the browser. This helps to quickly check the information we are placing in the database.
Schemas:
Neo4j User Nodes
(Labels: Person, Gender)
"name": <String>,
"id": <String>
FirebaseFirestore:
Collection: users
document<user id>
"age":<String>
"city":<String>
"name": <String>,
"gender": <String>
"img_url":<String>
Adding Friends
Moving on I next added functionality for the addition of friends for users. This is is crucial to the app because the core functionality involves matching your friends with your other friends. Adding friends was created both in Firebase and Neo4j although we only really use the Neo4j to add the friends. To create friends in Neo4j we break the process into 3 steps. First users have to be able to send friend requests to users, then users have to be able to accept friend request, and finally users need to be able to see a list of their friends. In the UI for the app we break these actions into two tabs. We have one tab listing all friends for the user. The second tab prints a list of all users and allows the user to send a request through a button press. The second tab also list all friend request a user has received and allows for acceptance or denial. In our backend we handle the friend requests by creating an edge in between nodes. We pull all nodes connected by a friend request edge of the user to get the list of friend request. Upon acceptance of a request, we destroy this request edge and replace it with a friend edge.
We also created a friend list in FirebaseFireStore because we wanted to reduce the amount of queries that we sent to the Neo4j server. By having the list in Firebase we can easily pull a list of friends from there. Especially as the number of friends grows, this would make it easier to process this request.
Schemas:
Neo4j Friend Edges
friendRequest - one directional edge between two Persons
friends - bidirectional edge between two Persons
notfriends - bidirectional edge between two Persons
FirebaseFirestore:
Collection: friends
document<user id>
<id>:<name>
Matching
For Matching we used Neo4j. Matching worked similarly as the friending concept except that instead of a user directly sending a request, a friend of the two users would do it. This broke our process up for matching into the following:friend of users must match users, both users must accept, chat functionality must be enabled between matched users. This is also created a unique issue in that we want to be able to keep track of exactly who has endorsed a match. To accomplish all of this I incorporated the use of a "match node". Using this match node I would keep track of who had been matched within the node and use edges to the node to denote whether someone endorsed the connection or not. This also made it easier in terms of retrieval. Getting the number of endorsers was as easy as counting connections to the match node. Deciding when a match had been successfully completed required me to evaluate 2 states: Either both had accepted or one user had rejected the pairing. I didn't want to evaluate this everytime I pulled information from Neo4j so I also created a "Match Complete" node that every node would point to when it was complete. Users would only be shown matches that were still open and upon acceptance they would either accept the match which changed the edge to node or they would complete the match which would also create an edge to the Match Complete node and open chat functionality if applicable.
Schemas:
Neo4j Match Nodes and Edges
Match Node
(Labels: match)
"femaleId":<string>
"maleId":<string>
"femaleName":<string>
"maleName":<string>
Match Complete Node
(Labels: matchComplete)
Edges
endorse - edge pointing from Person node to match node. Has parameters of "type":<string>
matchedWith - edge pointing from Person node to match node. Has parameters of "status":<string>
matchComplete - edge pointing from match node to matchComplete node
Chatting
I implemented the chat feature using Firebase Realtime Database. Firebase Realtime Database differed from the FirebaseFirestore in that it is real time and also follows a different NoSQL structure. It is still just a nested hierarchy of information however. I designed the UI so that users would see a list of individuals to chat with. Upon selecting an individual they would be shifted to a chat room where they could message one another. Using the realtime database allowed for realtime updates. I created the backend using a heiracrhcy of chatrooms. Each chatroom was given a unique ID. I created a list of chat room IDs alongside user information in Firebase Firestore to keep track of who they were allowed to chat with. I used this list to populate the UI list. Inside the chat room heiracrhcy chats are ordered by a sequential key that increments every time a new chat is made. I keep track of which user sent the message and the contents of the message.
Firebase Database Chat Schema
Chat
Chat ID <Int> Message Number <Int> "ID": <String> "Name":<String> "Message":<String>
Results
Ultimately the main functions of the app were completed.
However due to time constraints the app has several issues.
UI/UX
The UI is terrible and bland and rife with tiny errors that can make it a nightmare to use. For example I didn't have time to implement notifications for every action that a user takes. So a user might hit a button a some action will happen on the backend but the user will not be alerted to this. In many places the UI will also not shift properly which is very important from a user perspective. After testing with different devices, I also noticed that it doesn't scale properly to different screen sizes
The app is also just not very fun to use at all. I can chalk this up to the core functionality of the app being too bare on its own to elicit excitement from users. I realize after building it that the UX is very important in keeping users engaged and actually creating a product that depends on having users use it for the purpose to actually make sense. Looking at similar apps such as Tinder, Bumble, or OKCupid, I realize they have certain ways they gamify the process to make it more enjoyable to users. My app has none of this and I think it is a crucial element.
Databases
Over the course of building this app I ended up using three different databases which present it's own set of unique challenges. All of the databases have different loads restraints and different structures. While each was useful on its own for specific functionality, it was a nightmare to actually learn how to use them all and have to restructure my data uniquely for each database. Each database also had severe limitations that were at times very difficult to get through. In terms of moving data in between sources, it is time consuming to develop three different injection methods for three different databases.
Neo4j scaling issues
Neo4j turned out to be great at graph functionality but the size of it ultimately turned me off to using it in the future. This was partially because I was using a free version of Neo4j on a free Tier service of Amazon AWS. Neo4j frequently reminded me that it did not have the standards it wanted to have maximum capability. To put this in perspective, Neo4j requested 8 GB of ram at a minimum and the ability to use 40,000 reads and writes simultaneously. My Amazon AWS server had 2GB of ram and I gave Neo4j about 1024 reads/writes. This produced a sense of dread in me whenever I used the database because I feared I would put too much data inside it of and it grow large enough that Amazon would begin charging me money. The actual cost of running a "real" Neo4j server was outside the realm of my pockets. If I was to turn this into a production app, I don't think that I would use Neo4j at all.
Neo4j's cypher language was very intuitive and easy to use. Although I didn't have the time to get to the actual fun tasks of using graph algorithms to create better matches, the path to do so was clearly laid out. In the future I think Neo4j would be a great way of quickly testing algorithms, but I would use a different database with much less scaling costs that could implement some of the graphing functionality I needed.
Lack of Analytical Components
A big draw for building this app was to implement network algorithms on social network data to provide high quality match suggestions to users. It never quite reached this point due to time constraints. The app in it's current form does not use any special techniques to develop the matching queue between users. This is a major area of improvement.
Next Steps
- Improve UI - make the app more visually pleasing
- Incorporate algorithms in deterring matching queues
- Add gamification to the app to improve the user experience - Keep track of how many successful matches users have, add a score system, etc.
- Switch away from Neo4j - Neo4j is great but switching to another database would make it much easier to scale and eventually launch as a product
Poster
References
I used a great amount of references while learning how to develop in android. If I directly copied code this is noted in my code in Github.
- Review prediction with Neo4j and TensorFlow – Octavian – Medium
- Graph Databases: Talking about your Data Relationships with Python
- Sending Messages from App Server to Clients Using FCM
- Firebase Tutorial: Real-time Chat | raywenderlich.com
- (1) What is Facebook's architecture? - Quora
- How does Facebook maintain a list of friends for each user? Does it maintain a separate table for each user? - Quora
- I want to implement a database with my Android app that incorporates a User Registration feature. Users will be able to create friends lists, and I’ll store the user information, pictures, and listings. Will NOSQL DB or a relational DB be better? - Quora
- Firebase firestore collection count - Stack Overflow
- How to Code a Bottom Navigation Bar for an Android App
- Communicate with other fragments | Android Developers
- android - Fragment re-created on bottom navigation view item selected - Stack Overflow
- Android Kotlin: Bottom Navigation + Tab Layout – Avin Riyan – Medium
- Android Material Design Tabs (Tab Layout) with Swipe
- mitchtabian/TabFragments: How to use Tabs in Android Application
- Android Tab Tutorial (Android Studio Tab Fragments) - YouTube
- mitchtabian/NavigateWithFragmentsTutorial2: Learn how to use the navigation bar and fragments!
- java - Call a Fragment method from an Adapter - Stack Overflow
- java - How to create interface between Fragment and adapter? - Stack Overflow
- dictionary - String to HashMap JAVA - Stack Overflow
- Set Viewpager height inside Scrollview in android - Stack Overflow
- Android NestedScrollView/ScrollView wrapping ViewPager adaptive height | kankan968
- How to Develop a Boilerplate for API with Node.js, Express, and MongoDB
- How to call a Python function from Node.js - Stack Overflow
- Max De Marzi | Graphs with Neo4j
- Installing Java 8 on AWS EC2 Amazon Linux Instance - DZone Cloud
- Download Java for Linux
- How to install Java on CentOS 7 | Linuxize
- amazon ec2 - Connecting to neo4j on ec2 - Stack Overflow
- Tutorial: Creating and managing a Node.js server on AWS, part 1
- Neo4j from JavaScript - Neo4j Graph Database Platform
- curl POST examples
- Retrofit— A simple Android tutorial – Prakash Pun – Medium
- Building a Dating site with Neo4j – Part Two | Max De Marzi
- maxdemarzi/dating_site: Example Dating Site with Neo4j
- Using Neo4j to build a recommendation engine based on collaborative filtering - Linkurious
- Android Chat Tutorial: Building a Messaging UI | SendBird Blog
- java - Logging with Retrofit 2 - Stack Overflow
- Bottom Navigation Android Example using Fragments
- ConstraintLayout
- ConstraintLayout | Android Developers
- Firebase Guides | Firebase
- bumptech/glide: An image loading and caching library for Android focused on smooth scrolling
- How to upload data to Firebase Firestore Cloud Database
- How to Code a Bottom Navigation Bar for an Android App
- When and why should I use fragments in Android applications? - Stack Overflow
- android - Dilemma: when to use Fragments vs Activities: - Stack Overflow
- Import material design icons into an android project - Stack Overflow
- Bottom Navigation Android Example using Fragments
- Communicate with other fragments | Android Developers
- Android Material Design Tabs (Tab Layout) with Swipe