2

In my app, I'm implementing a questionnaire system and I'd like to implement tags for questions -- very similar to tags in questions here or Stack Overflow.

I wanted to get some advices on how to implement this as a property in my object. Should they be an array of strings -- as below?

{
  "id": 123,
  "question": "What is your favorite color?",
  "tags": [
     "personality trait",
     "likes and dislikes"
  ]
}

Or is it better to use some type of identifier, instead of the actual verbiage?

{
   "id": 123,
   "question": "What is your favorite color?",
   "tags": [1234, 89645]
}

I'm thinking about storing these questions in a NoSQL database and I want users to be able to run queries based on these tags. For example, if someone wants to pull all questions that are about "personality traits", I should be able to run a query that contains that particular tag.

  • I prefer the strings over the ID. But be sure you guard against injection attacks since this is user input. – candied_orange Nov 30 '17 at 3:22
  • When I use tags, I use them exactly as that: tags. They are metadata correlators, and get put into the tags array as bare strings. You could, of course use integer surrogates to "safe" tags, but I've never needed to do that. Soundex the tags to smooth out any variations, run frequency heuristics, and have at it! – K. Alan Bates Nov 30 '17 at 3:29
  • @K.AlanBates If I'm following you correctly, you're suggesting the first approach in my post. Is that correct? – Sam Nov 30 '17 at 3:38
  • @Sam I think so. Unless you've got additional requirements or you're working with technology that won't allow you to mine tags in a performant manner, string-based tags should be ok for capturing what you're looking for. at the very least, it's what I would start with. – K. Alan Bates Nov 30 '17 at 4:06
4

Short answer

It depends on what you intend to do with the tags from an application point of view. If it's just for searching in a single user language, and if the accuracy of the tag is not critical, just go for the string. But in all the other cases, the id would be a better candidate IMHO.

Detailed answer

In option 1 (string) you consider the tag to be a simple string value (aka value object) embedded in the document. This has the following consequences:

  • The good point is that all the needed values corresponding to an object are obtained in a single query, and the tags will be very easy to use in queries.
  • Multilingual tagging (i.e. each user uses tags in his/her own language) would unfortunately be much more expensive : the tag's just a string and there's no semantic that relates it to other strings in other languages. So forget this option if internationalization could be in scope.
  • A tag collection could later be created to enrich the tags with additional information, such as for example a short title, a description and tag synonyms (like on StackExchange). But it would be more expensive to use, because it would require queries for a tag document searching by string. A string index can increase search efficiency, but not to the point of access via an id.
  • Strings take in general more space. If you have millions of tags, that'll be quite some space wasted for redundant data.
  • It would require more efforts to show the user an exhaustive list of tags (e.g. for auto completion). So the tag information risks to be less reliable.

In option 2 (id) you consider the tag to be an independent entity (in the DDD sense) using MongoDB's normalized data model instead of its embedded model. The consequences are:

  • The main inconvenience is that applications must use additional queries to resolve the reference and get the tag name. But if you need multilingual tags, or if your application needs anyway to access other tag related information, this will not be a real overhead.
  • The main advantage is that you'll already have tag documents, to enrich the tags as the needs grow.
  • Accessing a tag document using a reference is very fast (faster than going via an index indirection).
  • The tagging information is compact (a document reference is currently about 12 bytes).
  • The normalized model avoids the performance consequences of mutable, growing arrays, if the tagging is frequently updated.
  • You use a mechanism that is designed to manage one to many relations between independent entities.
  • You can develop complex searches using relations between tags (e.g.synonyms, inclusion).

Advice

Personally, as I am working in an international environment, I'd immediately go for option 2. The problem is that if you start with option 1, it'll be difficult to evolve afterwards. For instance, I suspect that someone at LinkedIn used string tags in the db model when the skills tagging was initially launched, so that several years later, although you can display your profile in several language, the skill tags are untranslated so usable only in english or by mixing different languages.

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.