0

Is there a way to sort by a given array?

something like this:

const somes = await SomeModel.find({}).sort({'_id': {'$in': [ObjectId('sdasdsd), ObjectId('sdasdsd), ObjectId('sdasdsd)]}}).exec()

What i looking for is a way to get a solution, to get all document of the collection and sort by if the document's _id match with one of the given array.

An example:

we have albums collection and songs collection. In albums collection we store the ids of the songs that belongs to the albums.

I want to get the songs, but if the song is in the album take them front of the array.

I solved this as follow, but its looks a bit hacky:

const songs = await SongMode.find({}).skipe(limit * page).limit(limit).exec();
const album = await AlbumModel.findById(id).exec();

if(album) {
    songArr = album.songs.slice(limit * page);

    for(let song of album.songs) {
        songs.unshift(song);
        songs.pop();
    }
}
5
  • Could you explain bit more. What does item contain? Commented Dec 5, 2018 at 18:08
  • items is an array of _ids Commented Dec 5, 2018 at 18:14
  • Could you expand on what you mean by "sort by a given array"? Please be more clear and detailed about what the documents might look like and the resulting behavior you want to see. There isn't much to go in with what you've provided here. Commented Dec 5, 2018 at 20:32
  • @B.Fleming, Anthony Winzlet I updated the question to be more clear. Commented Dec 5, 2018 at 21:30
  • You can either use $indexOfArray. Something like db.collection.aggregate([ { "$addFields": { "order": { "$indexOfArray": [arrayOfIds, "$_id"] } } }, { "$sort": { "order": 1 } } ]) Commented Dec 6, 2018 at 13:28

1 Answer 1

1

This cannot be accomplished using an ordinary .find().sort(). Instead, you will need to use the MongoDB aggregation pipeline (.aggregate()). Specifically, you will need to do the following:

  1. Perform a $projection such that if the _id is $in the array, your new sort_field is given the value 1, otherwise it's given a value of 0.
  2. Perform a $sort such that you're doing a descending sort on the new sort_field.

If you're using MongoDB version 3.4 or greater, then this is easy because of the $addFields operator:

const your_array_of_ids = [
    ObjectId('objectid1'),
    ObjectId('objectid2'),
    ObjectId('objectid3')
];

SomeModel.aggregate([
    { '$addFields': {
        'sort_field': { '$cond': {
            'if': { '$in': [ '$_id', your_array_of_ids ] },
            'then': 1,
            'else': 0
        }}
    }},
    { '$sort': {
        'sort_field': -1
    }}
]);

If you're using an older version of MongoDB, then the solution is similar, but instead of $addFields you will be using $project. Additionally, you will need to explicitly include all of the other fields you want included, otherwise they will be excluded from the results.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.