TonyW
TonyW

Reputation: 18875

Loopback: Saving one-to-many relations in MongoDB

From my reading of the documents and the model relations examples, I didn't see how you would save one-to-many relations in MongoDB. I have the following models:

1. Category
2. Post

Category has many Posts and Post belongs to Category The foreign key I used is "categoryId"

I used the following scripts to insert sample data into MongoDB:

create-categories.js:

var categories = [
        {"title" : "Technology Matters", "description": "Blogs on latest technologies"},
        {"title" : "Innovative Ideas", "description": "Innovative ideas on the next project"},
        {"title" : "Comments on Hot Topics", "description": "My comments on the hot topics"}
];
module.exports = function(server) {
        var dataSource = server.dataSources.mongoDatastore;
        dataSource.automigrate('Category', function(err) {
                if (err) throw err;
                var Model = server.models.Category;
                //create some sample data
                var count = categories.length;
                categories.forEach(function(category) {
                        Model.create(category, function(er, result) {
                                if (er) return;
                                console.log('Category created: ', result);
                                count--;
                                if (count == 0) {
                                        console.log('Categories all created!');
                                        dataSource.disconnect();
                                }
                        });
                        //could define a model scope here
                });
        });
};

create-posts.js:

var posts = [
        {"title" : "Post 1 Title", "bodyText": "body text for blog post 1", "dateCreated": new Date(), "categoryId": 1},
        {"title" : "Post 2 Title", "bodyText": "body text for blog post 2", "dateCreated": new Date(), "categoryId": 1},
        {"title" : "Post 3 Title", "bodyText": "body text for blog post 3", "dateCreated": new Date(), "categoryId": 2},
        {"title" : "Post 4 Title", "bodyText": "body text for blog post 4", "dateCreated": new Date(), "categoryId": 2},
        {"title" : "Post 5 Title", "bodyText": "body text for blog post 5", "dateCreated": new Date(), "categoryId": 1},
        {"title" : "Post 6 Title", "bodyText": "body text for blog post 6", "dateCreated": new Date(), "categoryId": 3},
        {"title" : "Post 7 Title", "bodyText": "body text for blog post 7", "dateCreated": new Date(), "categoryId": 2},
        {"title" : "Post 8 Title", "bodyText": "body text for blog post 8", "dateCreated": new Date(), "categoryId": 3},
        {"title" : "Post 9 Title", "bodyText": "body text for blog post 9", "dateCreated": new Date(), "categoryId": 1},
        {"title" : "Post 10 Title", "bodyText": "body text for blog post 10", "dateCreated": new Date(), "categoryId": 2}
];
module.exports = function(server) {
        var dataSource = server.dataSources.mongoDatastore;
        dataSource.automigrate('Post', function(err) {
                if (err) throw err;
                var Model = server.models.Post;
                //create some sample data
                var count = posts.length;
                posts.forEach(function(post) {
                        Model.create(post, function(er, result) {
                                if (er) return;
                                console.log('Post created: ', result);
                                count--;
                                if (count == 0) {
                                        console.log('Posts all created!');
                                        dataSource.disconnect();
                                }
                        });
                        //could define a model scope here
                });
        });
};

Please note that 'categoryId' faked up in each post object above is just temporary, I wish to save the actual categoryId from MongoDB to each post object.

My question is: when saving each post object to MongoDB, how would you get the owner's ID (in this case, categoryId). The categories saved in my MongoDB are following, each of them has an _id that is ObjectId type. Is it necessary to save the category ObjectId as a foreign key in Post collection? and if yes, how?

{
        "_id" : ObjectId("55355f076ed9d911089ea0a7"),
        "title" : "Technology Matters",
        "description" : "Blogs on latest technologies"
}
{
        "_id" : ObjectId("55355f076ed9d911089ea0a8"),
        "title" : "Innovative Ideas",
        "description" : "Innovative ideas on the next project"
}
{
        "_id" : ObjectId("55355f076ed9d911089ea0a9"),
        "title" : "Comments on Hot Topics",
        "description" : "My comments on the hot topics"
}

Upvotes: 2

Views: 1288

Answers (1)

Nachiket Kate
Nachiket Kate

Reputation: 8571

Tony few suggestions for you,

  1. NoSQL doesn't believe in normalization. Its fine to store same data at many places.
  2. In MongoDB, one-many relationship can be handled in a single document if one-many relationship is not too large i.e. one < many and not one << many and cardinality of one is not very high.

Solution to your problem could be, A category can have multiple posts but how many categories will be present in all. In my opinion count of one (category) is very less as compared to posts.

Better way to store data can be as,

create a collection called posts like,

{
      "title" : "Post 1 Title", 
      "bodyText": "body text for blog post 1", 
      "dateCreated": new Date(), 
      "category": "movie"
}

In some cases it can happen that post will fall under 2 categories

{
      "title" : "Post 1 Title", 
      "bodyText": "body text for blog post 1", 
      "dateCreated": new Date(), 
      "category": ["movie","drama"]
}

Still this is also a good design and will work very well with lot of data. Performance of operations will also improve as all related data is stored at a single location which is real strength of NoSQL.

Upvotes: 2

Related Questions