Search code examples
mongodbmongoose

Update array of Refs with sorted array in Mongo collection


I have three Mongoose schemas, User, ShowsList and Show. They are as follows (simplified for brevity):

User schema:

name: {
        type: String
},
email: {
        type: String
},
password: {
        type: String
},
role: {
        type: Number
};

ShowsList schema:

showsListOwner: {
        type: mongoose.Schema.Types.ObjectId,
        ref: 'User'
},
shows: [{
        type: mongoose.Schema.Types.ObjectId,
        ref: 'Show'
}]

Show schema:

showId: {
        type: Number
},
showName: {
        type: String
},
showPremiereDate: {
        type: String
}

Every time I add a show to the ShowsList.shows array, I use the Mongoose unshift operator to add a given Show's ObjectId into the first position of the ShowsList.shows array.

I have created a button in my app that sorts the array alphabetically by the populated showName field. I am able to query the array, populate it and sort alphabetically, but I can't figure out how to update/save the sorted array. My code on the backend is:

const userId = req.body.user._id;
const showsListPopulatedSorted = await ShowsList.findOne(
            {
                showsListOwner: userId
            }
        ).populate(
            {
                path: 'shows',
                options: {
                    sort: {
                        'showName':1
                    }
                }
            }
        );

I am unsure where to go from here. I have tried await showsListPopulatedSorted.save(); But the given user's ShowsList.shows array is still unsorted after the save. I have tried using await showsList.shows.deleteMany({}); to clear out the array before saving, but this does not help either.

I know how to add/remove one or more elements/documents to/from a Mongo array, but I can't seem to figure out how to replace the entire array with a newly-sorted version.

If someone can point me in the right direction of how to successfully perform the last step of swapping out the unsorted ShowsList.shows array for the alphabetically sorted ShowsList.shows array, I would greatly appreciate it!


Solution

  • I figured it out after another hour of plucking away at it!

    After getting the full ShowsList document for a given user, I extracted the shows array of populated Refs from it into its own variable. I then used a .map() function to build an array of just the ObjectIds, then set the shows ObjectId array within the full document equal to the newly-built array of ObjectIds from the sorted shows array and saved the whole document.

    After doing this, the list of ObjectId Refs now appears in the alphabetical order of their respective showName string values in the Mongo collection document.

    Here is the full code from the backend route that does the work:

    exports.sortShows = async(req, res, next)=>{
        const userId = req.body.user._id;
        try{
            const showsListPopulatedSorted = await ShowsList.findOne(
                {
                    showsListOwner: userId
                }
            ).populate(
                {
                    path: 'shows',
                    options: {
                        sort: {
                            'showName':1
                        }
                    }
                }
            );
            const showsListPopulatedSortedShows = showsListPopulatedSorted.shows;
            const showsObjectIdArray = showsListPopulatedSortedShows.map((show)=>{
                return show['_id'];
            });
            showsListPopulatedSorted.shows=showsObjectIdArray;
            await showsListPopulatedSorted.save();
        }catch(err){
            console.log(err);
        };
    };