Mongodb – Dynamic relations in MongoDB

mongodbrelational-theory

I'm designing a document with MongoDB where users have relationships with each other. Easy enough, right?

{
    _id: "012",
    username: "happy4u",
    // ...
    related: [
        '123', // user ids
        '456',
        '789'
    ]
}

But then I want to check if some user (the above), has some attribute in common with other guys in his relation. This is also easy, right?

But what if I wanted to check what he has in common with other guys related to the users in his own related list, not just one level, but multiple levels?

I thought of having a loop over the related list and then checking the result, then have another find in those results and have another one in the result's results, … but this makes no sense to me.

Then I thought of having a separate document for each user and storing their relations, perhaps 4 levels of relation. Something like an index of my own. This also is very hard to keep clean and every update in some user's list will require updates in this document. Not just one place but in multiple places. This way also makes no sense to me.

How can I achieve my goal? Do I need to change my schema? How can I design my schema to be more dynamic?

Best Answer

The pattern you describe is known as "friend of a friend." Here are a couple of answers on SO which may guide you.

In the relational database world the friends would be found by following foreign keys. Document DBs, however, eschew explicit foreign keys enforced in the DBMS and join-like functionality in favour of other benefits. It is down to your application to recurse over successive results, even if that "makes no sense."

If you are able to expand your technology stack, a graph database would provide an excellent solution to this particular use-case. You could hold just the user-user connections to get the total list of UserIDs to whatever depth was required, then look each up in MongoDB; or you could hold the attribute values, too, and filter on like-values in the graph DB.

To speed the like-value search in MongoDB you could store a document for each attribute value, each with an array of all users who have that value. For a given user you would then retrieve his record and the record for the given user's attribute value. The intersection of the user's friends and the attribute's user list are the friends-with-the-same-value. Two documents only must be read rather than however many friends the given user has. Similarly on update only two documents must be written. Sadly this does not help with finding friends-of-friends, of course.