Get Even More Visitors To Your Blog, Upgrade To A Business Listing >>

query on many to many relation mongodb database struct

query on many to many relation mongodb database struct

Problem

I have two collections in MongoDB: one saves post data of blog, the other saves comment data of blog with below schemas. How can I use nodejs and mongoose to Query all posts with comment belong to it and respond to single page application?. Thanks!

var PostSchema = mongoose.Schema({
    created: {
        type: Date,
        default: Date.now
    },
    content: {
        type: String,
        default: '',
        trim: true
    },
    user: {
        type: Schema.ObjectId,
        ref: 'user'
    }
 }); 

 var CommentSchema = mongoose.Schema({
    created: {
        type: Date,
        default: Date.now
    },
    content: {
        type: String,
        default: '',
        trim: true
    },
    ofpost: {
        type: Schema.ObjectId, 
        ref: 'post'           //which post this comment belong to
    },
    user: {
        type: Schema.ObjectId,
        ref: 'user'
    }
 }); 




    var Post = mongoose.model('Post', PostSchema);
    var Comment = mongoose.model('Comment', CommentSchema); 

//example:the Comment1 and Comment2 belong to Post1
    var Post1 = new Post({ content: 'good day', user: 'John' });
    var Comment1 = new Comment({content: 'yeah', ofpost: Post1._id, user:'Tom'})
    var Comment2 = new Comment({content: 'agree', ofpost: Post1._id, user:'Tina'})
Problem courtesy of: Vo Thanh Thang

Solution

As mongodb is NoSQL type of database and has no JOIN's or any sort of relationship between documents, you have to take care of such.
There are generally two ways to do so:

Caching
Consider storing comments data within blog document. You can have embedded documents without any problem. In reality it leads to some extra caches, like comments count, array of user id's of comments and other stuff that will make your queries indexed and more easy ways to search through collection.

Multiple Queries
If you still need separate collections, then you need to 'simulate' joins. Most efficient ways is to make temporary indexing arrays and multiple queries to different collections. Usually it should be just 2 queries for one Join (many to many), and small iteration to add second query documents to first array of documents.

Here is the flow that is suitable and performs well still, on example:
Two collections, first is posts, and second is comments which has id of post.

  1. Make query to posts.
  2. Iterate through each post and add its id into postIds array, as well make postMap object where key will be id of post and value will be specific post. - this is so called indexing posts.
  3. Make query to comments collection with $in argument with postIds array of post id's. This collection should have indexing on post id field in order to make this query very efficient. As well this query can include sorting by date (additional compound indexing will speedup it).
  4. Iterate through each comment and using postMap add it to comments array of post.

So we have only 2 queries, and one iteration through all comments to embed data into posts O(n). Without second step, adding to posts will be potentially O(p*c) where p - number of posts and c - number of comments. Which is obviously much slower as well on big queries can be potentially slow.

Summary
Second approach is more manageable approach from data point of view, as well is easier on writes, while is more complicated on reads.
Still will require some caching, like number of comments for blog posts.

Solution courtesy of: moka

Discussion

View additional discussion.



This post first appeared on Node.js Recipes, please read the originial post: here

Share the post

query on many to many relation mongodb database struct

×

Subscribe to Node.js Recipes

Get updates delivered right to your inbox!

Thank you for your subscription

×