0

Hi in mongo DB I have a table "games" like this:

{
"_id" : ObjectId("53c66f922e15c4e5ee2655af"),
"name" : "alien-kindergarden",
"title" : "Alien Kindergarden",
"description" : "Alien description",
"gameCategory_id" : "1",
"deviceOrientation_id" : "1",
"position" : "1"
}

and I have a few dictionaries (also simple collections in MongoDB) like "gameCategory" for example:

{
    "_id" : 0,
    "name" : "GAME_CATEGORY_NO_CATEGORY"
}

{
    "_id" : 1,
    "name" : "GAME_CATEGORY_POPULAR"
}

How to get data from collection "games" with fields from my dictionary like:

 {
    "_id" : ObjectId("53c66f922e15c4e5ee2655af"),
    "name" : "alien-kindergarden",
    "title" : "Alien Kindergarden",
    "description" : "Alien description",
    "gameCategory" : GAME_CATEGORY_NO_CATEGORY, <---------------
    "deviceOrientation_id" : "1",
    "position" : "1"
    }

Thanks. I'm using Node server for it.

Community
  • 1
  • 1
Simcha
  • 3,300
  • 7
  • 29
  • 42

1 Answers1

1

What you are essentially asking for is a "JOIN" as in SQL. Your first point of reading should be that MongoDB does not do joins. The general concept here is "embedding" where the related information is actually contained within the document.

A good reading of the Data Modelling section of the official documentation can cover various points such as this and alternate approaches. But in most cases the data you wish to reference should just be part of the original document:

{
    "_id" : ObjectId("53c66f922e15c4e5ee2655af"),
    "name" : "alien-kindergarden",
    "title" : "Alien Kindergarden",
    "description" : "Alien description",
    "gameCategory" : "GAME_CATEGORY_POPULAR",
    "deviceOrientation_id" : "1",
    "position" : "1"
}

This is generally because the MongoDB concept of being "scalable" is that all operations only ever deal with one collection at a time and "JOINS" are not attempted.

There are options available under node.js such as Mongoose that allow you to .populate() items from another "related" collection. But the general problem here is that you cannot "query" on the "related" information. All this really implements is a "query behind the scenes" approach. So more than one query is actually executed. To find by "related" information the best approach is generally:

var catId = db.category.findOne({ "name": "GAME_CATEGORY_POPULAR" })._id;

db.category.find({ "gameCategory_id": catId })

As nothing will let you query the "game" collection by a value held in a foreign collection.

The idea of "embedding" and generally "duplicating" data might seem alien to those used to relational database concepts. But really your reason for applying a solution such as MongoDB should be that you realize certain "relational patterns" are not the "best fit" for your application.

If you have not looked at this in that way, then perhaps you should stick with the relational database approach and use those tools. At least until you "find" the actual shortcomings and realize why you need to "design" around that.

Unlearn what you have learned.

Community
  • 1
  • 1
Neil Lunn
  • 148,042
  • 36
  • 346
  • 317
  • Thanks for good answer. The reason why I still use relations instead of embedding for this particular case: It because on my client side I also should give to user combobox with all categories that I have in my DB. If you have another approach for this, so I will be glad to listen it. – Simcha Jul 31 '14 at 08:40
  • 1
    @Simha Well there are several approaches but there generally is no reason not to have a collection just because you are embedding data. In various cases the best approach is to basically "embed some but not all" and otherwise retrieve the "full" information from the other collection document. It mainly is, just a different level of thinking form relational that says "normalize everything". NoSQL usually means "model how you actually use it" – Neil Lunn Jul 31 '14 at 08:46
  • Ok, so according this approach, for example If I will need to change game category name from GAME_CATEGORY_POPULAR to GAME_CATEGORY_SUPER_POPULAR because in my client side logic of application was changed, so I will need for all documents in collection "games" to change field "category", but if my data was normalized, I will need to change just one field in my collection? Isn't it? – Simcha Jul 31 '14 at 09:02
  • @Simha Understand this one point. The cost of "duplication" and possible multiple update points needs to weighed against the cost of making a singular query to many. A NoSQL staple is "understanding your usage patterns" and then designing accordingly. Which one suits you? Retrieve once and update many? Or Retrieve many and update once? The difference is subjective to usage and there is no "one definitive answer". If you are still struggling, then ask another specific question. You are sure to get an answer. – Neil Lunn Jul 31 '14 at 09:10