How to tag documents in MongoDB?

Viewed 130

I need to tag documents in a collection, let's call it 'Contacts'.

The first idea I had was to create an attribute called "tags" for each document. Well, in this case we have something like:

{
_id:'1',
contact_name:'Asya Kamsky',
tags:['mongodb', 'maths', 'travels']
}

Now, let's suppose that we have users that want to tag any document in 'Contacts'.

If we keep the decision to save the tags attribute for each document, as the tags are personal, we need to use the userId for each tag. So our document would be something like that (or not):

{
_id:'1',
contact_name:'Asya Kamsky',
tags:[
{userId:'alex',tags:['mongodb', 'maths', 'travels']},
{userId:'eric',tags:['databases', 'friends', 'japan']},
]
}

Now, let's complicate it a bit. Let's imagine that we have A LOT of users and each one want to tag documents with his personal tags.

How to deal with that?

Ok, we could create thousands of tags for each document:

{
_id:'1',
contact_name:'Asya Kamsky',
tags:[
{userId:'alex',tags:['mongodb', 'maths', 'travels']},
{userId:'eric',tags:['databases', 'friends', 'japan']},
{.....................................................}
{.....................................................}
{......................................................}
]
}

But, what if we have millions of users? In this case we have a 16mg limitation for each document, as I know....

At this point, worrying about the future growth of my application, I decided to create a nice separated collection called 'tags' that would contain documents similar to:

{
    "contact_name" : "Asya Kamsky",
    "useriId" : "alex",
    "tags" : ['mongodb', 'maths', 'travels'],
    "timestamp" : "2017-08-08 14:33:28"
},

{
    "contact_name" : "Asya Kamsky",
    "useriId" : "eric",
    "tags" : ['databases', 'friends', 'japan'],
    "timestamp" : "2017-08-08 14:33:28"
}

That's, we have a separated documents that represent a tag of each user.

Cool and clean, right?

Well, i this case, we face 2 problems:

  1. Minor problem: We return to the SQL logic that I don't like anymore but I accept in some cases.
  2. Big (for me) problem: how to search a contact by PERSONAL tags? In this case we have a nice 'JOIN' problem that MongoDB resolves well using $lookup. "Resolves well" for 10000, 20000, or even 500000 documents. But as I want to ensure a good performance in the future, I think about 10000000 contacts. So, as I researched recently, the $lookup works well for a "small part" of universe and, even with indexes, this search would take a lot of time to be executed.

How to resolve this challenge?

Thanks all

1 Answers
Related