normativepcoder
normativepcoder

Reputation: 435

how to sort ,index and paginate posts mongodb-mongoose

I have the following postSchema and would like to fetch datas depending on updatedAt field. When people make comment I increase numberofreply by one and its updatedAt is updated. How should I fetch datas for infinite scroll and should I use indexing for this operation ?

const postScheme = mongoose.Schema(
    {
        post: {
            type: String,
            trim: true,
        },
        numberOfReply: {
            type: Number,
            default: 0
        },
        owner: {
            type: mongoose.Schema.Types.ObjectId,
            ref: 'User'
        },
        hasImage: {
            type: Boolean,
        },
        image: {
            type: String,
            trim: true
        },
    },
    {timestamps: true}
)

this is what I use to fetch first page

Post.Post.find({}).sort({'updatedAt': -1}).limit(10).populate('owner').populate('coin').exec(function (err, posts) {
    res.send(posts)
})

this is for infinite scroll

Post.Post.find({isCoin: true, updatedAt: {$lt: req.body.last}}).sort({'updatedAt': -1}).populate('owner').limit(
    10).exec(function (err, posts) {
    res.send(posts)
})

Upvotes: 1

Views: 1040

Answers (1)

Tom Slabbaert
Tom Slabbaert

Reputation: 22316

The limit, skip syntax is Mongo's way of paginating through data so you got that worked out, from a code perspective you can't really change anything to work better.

should I use indexing for this operation

Most definitely yes, indexes are the way to make this operation be efficient. otherwise Mongo will do a collection scan for each pagination which is very inefficient.

So what kind of index you should built? Well you want to build a compound index that will allow the query to both satisfy the query and the sort conditions, and in your case that is on the isCoin and updateAt fields, like so:

db.collection.createIndex( { isCoin: 1, updateAt: -1 } )

A few improvements you can make to make the index a bit more efficient (for this specific query) are:

  1. Consider creating the index as a sparse index, this will only index documents with both fields in them, obviously if the data doesn't include this options you can ignore it.

  2. This one has a few caveats in it, but partial indexes are designed for this case, to improve query performance by indexing a smaller subset of the data. and in your case you can add this option

{ partialFilterExpression: { isCoin: true } }

with that said this will limit your index usage for other queries so it might not be the ultimate choice for you.

Upvotes: 1

Related Questions