David Schultz

Just another programming blog.

MongoDB: Sorting by external weights

Date posted: March 22, 2018
Last updated: July 02, 2019

MongoDB aggregations can be sorted by any field in a document,
but they can also be sorted by external factors.

Say we have some documents with tags:

{'id': 'a', 'tag': 'foo'}
{'id': 'b', 'tag': 'bar'}
{'id': 'c', 'tag': 'baz'}
{'id': 'd', 'tag': 'foo'}
{'id': 'e', 'tag': 'bar'}
{'id': 'f', 'tag': 'baz'}
{'id': 'g', 'tag': 'foo'}

We can weight these documents by tag. Let's order them
'bar', 'foo', 'baz'. Any documents not tagged with those
three words will get ordered last. We can also limit
the output, asking for the first 3 documents.

db.collection.aggregate([
   {"$addFields": {
       "weight": {"$cond": [
           {"$eq": ["$tag": "bar"] },
           3,
           {"$cond": [ 
               {"$eq": ["$tag": "foo"] },
               2,
               {"$cond": [
                   {"$eq": ["$tag": "baz"] },
                   1,
                   0
               ]}
           ]}
       ]}
   }},
   {"$sort": { "weight": -1} },
   {"$limit": 3}
])

This gives the proper sorted result:

{'id': 'b', 'tag': 'bar'}
{'id': 'e', 'tag': 'bar'}
{'id': 'a', 'tag': 'foo'}

Note that the tagged documents may be returned in
any order, so it's undefined which bar is sorted first,
or which foo is the third result.