2

This is the first mongo-backed-application I am trying to make beyond tutorials, so I lack imagination when it comes to document schemas.

Context:

On a dating application, there is an algorithm that identifies matches between users. Currently trying to identify how these matches should be stored.

Current schema:

Create two Match documents per pair (one for each user), each will hold the response of its user, a reference to the other user, and the id of its paired document:

Match : {
  objectid: [unique uuid],
  user: [idx, uuid],
  targetUser: [reference to User],
  pair: [Match uuid],
  approved: [bool / null]
}

UseCase:

Algorithm creates the match objects. A request is made to fetch all potential User matches, we query the database for all the Match objects for User, where approved is null. The database will populate the targetUser field with the actual User document [!!!], and return. Results are serialized and sent back.

...

User approves match, request sent to update Match[objectid].approved = True. Backend checks value of second Match object referenced by pair and then fires other actions depending on value.

Concerns:

First of all, to someone more experienced with NoSQL this might seem horrible, in which case please tell me. My main concern is about having the reference to targetUser. A big selling point of NoSQL is reducing the number of 'joins', yet I can't find a way of avoiding it here. Also, the fact that I have two objects for one pair is a bit troubling. But how else would I say: give me all potential matches for User A ?

  • This particular case could be so much easier with an RDBMS, to my mind. To play the Mongo's strong suits, I'd take a case where documents can be large and have complicated, free-form, tree-like structure, with very little need for joins. – 9000 Mar 1 '17 at 16:56
  • All the other use cases I can currently think fit quite nicely to the nosql scheme. I will probably be taking an approach similar to Philip's suggestion – latusaki Mar 1 '17 at 16:58
4

When you design database schemas for MongoDB, the decision criteria number one is not "how is my data structured?" but rather "what queries do I want to perform on my data?". Your data schema should then be structured so that all performance-relevant use-cases can be fulfilled with a single query.

If your most important query is "get specific user with all unapproved matches", then you should have an array-field unapproved_matches in the User-document with all the unapproved Match-documents for that user. These match sub-documents should be populated with all the data you want to show on your frontend. So instead of just referencing the document of the other user, you will likely want to include information name, age, location, profile URL and/or profile picture URL.

That means an individual match document might exist multiple times in your database, two times in the users-collection as a sub-documents of the two users which need to approve/reject it and (if there is a use for that) yet another time as an entry in the global matches collection. You will also have some information which is duplicated between the User-document and the Match-documents which match to that user.

This might sound quite heretical to those used to working with relational databases. But the database you are working with is not relational. So forget everything Raymond F. Boyce and Edgar F. Codd told you about data normalization. Data duplication is not necessarily a bad thing in MongoDB. The price you pay for avoiding JOINs is that you often don't get around redundancies.

  • I had considered something similar, with the main price for this approach is that I will not have an updated profile for the matches, which I realise is not absolutely crucial. I will think about this, thanks ! – latusaki Mar 1 '17 at 14:19
  • @latusaki Exactly. Data redundancies mean that updates will be a much more convoluted process. If a user changes some information which shows in the matches, you will have to update all the match sub-documents of all users which reference that user. But keep in mind that this updating is not a performance-critical operation. You can do it in background and nobody will notice even when it takes several minutes until other users see the change. – Philipp Mar 1 '17 at 14:23
  • 1
    Data duplication's price is not storage, it's consistency. If you can handle multiple copies without consistency problems (e.g. using version numbers, or synchronized updates), duplication (aka denormalization) is OK. – 9000 Mar 1 '17 at 17:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.