Sort by Releveance

Hello All,

I want to create an API which returns a collection of documents which is sorted according to particular condition for e.g. like any filter query or something like Documents of India location at top, then other documents later. I also want to integrate pagination for the same.
Is there any solution or sample code for the same?
Thankyou in Advance!

Hi @Ashutosh_Mishra1,

Do you have any sample documents to share as well as an expected output? This would help clarify what you’re after and how it can possibly be achieved.

In addition to this, could you advise if you’re using an on-prem or Atlas deployment? Off the top of my head a few things that may help based off the information on this post:

Look forward to hearing from you.

Regards,
Jason

1 Like

Hi Jason,
Thankyou for the reply.
I am trying to explain my use case here.

Actually I have a database of let say 3000 users which are from different locations all around the globe.
I want to get these data through a NodeJS API which returns data in sorted order (Not Filtered).
Sorting can be done in multiple ways like

  1. Latest users coming first ( that I have implemented using {sort:created:-1}
  2. Old users coming first ( that I have implemented using {sort:created:1}
  3. Salary ({salary:-1})
    All these sorting returns all the data, just the ordering changes according to the sorting condition provided.

Similarly I want to create one more 4th filter which will be named as “Recommended”
4. Recommendation filter returns the users in sorted order according to the Logged in users interests. Like a user of USA is logged in then, I want users of USA to come at top, then others at later. Similarly I want to set some priorities to some fields to get the data in that sorted order. Hope this use case helps you understand my need.

P.s. I tried using $facet but that does’t seemed an optimized way to me as I am getting duplicate data many times, also I can’t face multiple priorities.Attaching a screenshot of sample code.

The following often helps more that explications.

To bad you went the explications route. For example, is the field industry an array or a single value? Is the rindustry variable, an array or a single value?

Check Run aggregation pipeline and sort results by a set of match priorities - #3 by steevej

The idea is to use $addFields/$set stage to set sort values for your relevance.

You will start with a $match stage like:

match = { "$match" : {
    "isVerified" : true
} }

The second stage sets the relevance values.

relevance = { "$set" : {
  "_tmp" : {
    "industry" : { "$cond" : [
      { "$in" : { "$industry" , rindustry } } , 0 , 1
    ] } ,
    "country" : { "$cond" : [
      { "$eq" : { "$location.country" , rcountry } } , 0 , 1
    ] }
  }
} }

The you will $sort using the relevance value and your other sort criteria.

sort = { "$sort" : {
  "_tmp.industry" : 1 ,
  "_tmp.country" : 1 ,
  "salary" : -1
} }

The a little cosmetic $unset to remove the _tmp fields.

unset = { "$unset" : "_tmp" }

The whole pipeline being:

pipeline = [ match , set , sort , unset ]

Please read Formatting code and log snippets in posts before posting new code or sample documents. It helps when we can just cut-n-paste your field names and/or your code.

Your $facet matches seem to be mutually exclusive so I wonder how you can have duplicates.

Since isVerified $match is the same in all facets, it should be move into its own $match before the $facet.

1 Like

Hi Steeve Juneau,
I tried implementing with the code you provided, which is below

StartupSchema.statics.getRelevantStartups = async function () {
    const startups = await this.aggregate([
        {
            $match: {
                isVerified: true,
            },
        },

        {
            $set: {
                _tmp: {
                    industry: {
                        $cond: [{ $in: { $industry: ['Cosmetics'] } }, 0, 1],
                    },
                    country: {
                        $cond: [
                            { $eq: { '$location.country': 'India' } },
                            0,
                            1,
                        ],
                    },
                },
            },
        },
        {
            $sort: {
                '_tmp.industry': 1,
                '_tmp.country': 1,
            },
        },
        { $unset: '_tmp' },
    ])

    return startups
}

But it gave me this error


Then I tried by removing this $ sign

       {
            $set: {
                _tmp: {
                    industry: {
                        $cond: [{ $in: { industry: ['Cosmetics'] } }, 0, 1],
                    },
                    country: {
                        $cond: [{ $eq: { 'location.country': 'India' } }, 0, 1],
                    },
                },
            },
        },

Then it gave me a different error

Can you please help me out with this? It will be a great favour.
Thanks in Advance

I did not provide

What I had was

which if I reformat using your coding style and value for rindustry gives:

"industry" : {
    "$cond" : [ { "$in" : { "$industry" , ['Cosmetics'] } } , 0 , 1 ]
}

So your syntax is subtly off compared to what I shared which might explain the errors your get.