Babak Abadkheir
Babak Abadkheir

Reputation: 2358

MongoDB Aggregate: Sorting by existing values first

My user has this field :

interestedIn: [{
        type: String,
        enum: [
            'art',
            'sport',
            'news',
            'calture',
            ...
        ],
    }],

and my video has this field:

categories: [{
            type: String,
            enum: [
                'art',
                'sport',
                'news',
                'calture',
                ...
            ],
        }],

So I need a Video query that has the following conditions:

I got this far with said query:

Video.aggregate([

        { '$match': {}},
        { '$unwind': '$categories' },
        { '$match': {categories: {$in: req.user.interestedIn}}},
        { '$group': {
            '_id': '$categories',
            'categories': { '$push': '$categories' }
        }},
        { '$sort': { 'categories': 1 } }
    ])

This is the result:

   "videos": [
        {
            "_id": "art",
            "categories": [
                "art",
                "art",
                "art",
                "art",
                "art",
                "art",
                "art",
                "art",
                "art",
                "art",
                "art",
                "art",
                "art",
                "art"
            ]
        },
        {
            "_id": "news",
            "categories": [
                "news",
                "news",
                "news",
                "news",
                "news",
                "news",
                "news",
                "news",
   "videos": [
        {
            "_id": "art",
            "categories": [
                "art",
                "art",
                "art",
                "art",
                "art",
                "art",
                "art",
                "art",
                "art",
                "art",
                "art",
                "art",
                "art",
                "art"
            ]
        },
        {
            "_id": "news",
            "categories": [
                "news",
                "news",
                "news",
                "news",
                "news",
                "news",
                "news",
                "news",
                "news",
                "news",
                "news",
                "news",
                "news",
                "news"
            ]
        }
    ]
}

Upvotes: 5

Views: 501

Answers (1)

s7vr
s7vr

Reputation: 75984

You can use $setIntersection to extract the matching elements followed by $size to count the matches.

$sort descending documents on number of matches.

Something like

Video.aggregate([ 
  {"$addFields":{ "numofmatches":{"$size":{"$setIntersection":["$categories", req.user.interestedIn]}}}}, 
  {"$sort":{"numofmatches":-1}} 
])

Upvotes: 4

Related Questions