sequelize findAll sort order in nodejs

node.jsExpresssequelize.js

node.js Problem Overview


I'm trying to output all object list from database with sequelize as follow and want to get data are sorted out as I added id in where clause.

exports.getStaticCompanies = function () {
    return Company.findAll({
        where: {
            id: [46128, 2865, 49569,  1488,   45600,   61991,  1418,  61919,   53326,   61680]
        },
        attributes: ['id', 'logo_version', 'logo_content_type', 'name', 'updated_at']
    });
};

But the problem is after rendering, all data are sorted out as follow.

46128, 53326, 2865, 1488, 45600, 61680, 49569, 1418, ....

As I found, it's neither sorted by id nor name. Please help me how to solve it.

node.js Solutions


Solution 1 - node.js

In sequelize you can easily add order by clauses.

exports.getStaticCompanies = function () {
    return Company.findAll({
        where: {
            id: [46128, 2865, 49569,  1488,   45600,   61991,  1418,  61919,   53326,   61680]
        }, 
        // Add order conditions here....
        order: [
        	['id', 'DESC'],
        	['name', 'ASC'],
        ],
        attributes: ['id', 'logo_version', 'logo_content_type', 'name', 'updated_at']
    });
};

See how I've added the order array of objects?

order: [
	  ['COLUMN_NAME_EXAMPLE', 'ASC'], // Sorts by COLUMN_NAME_EXAMPLE in ascending order
],

Edit:

You might have to order the objects once they've been recieved inside the .then() promise. Checkout this question about ordering an array of objects based on a custom order:

https://stackoverflow.com/questions/9755889/how-do-i-sort-an-array-of-objects-based-on-the-ordering-of-another-array

Solution 2 - node.js

If you want to sort data either in Ascending or Descending order based on particular column, using sequlize js, use the order method of sequlize as follows

// Will order the specified column by descending order
order: sequelize.literal('column_name order')
e.g. order: sequelize.literal('timestamp DESC')

Solution 3 - node.js

You can accomplish this in a very back-handed way with the following code:

exports.getStaticCompanies = function () {
    var ids = [46128, 2865, 49569, 1488, 45600, 61991, 1418, 61919, 53326, 61680]
    return Company.findAll({
        where: {
            id: ids
        },
        attributes: ['id', 'logo_version', 'logo_content_type', 'name', 'updated_at'],
        order: sequelize.literal('(' + ids.map(function(id) {
            return '"Company"."id" = \'' + id + '\'');
        }).join(', ') + ') DESC')
    });
};

This is somewhat limited because it's got very bad performance characteristics past a few dozen records, but it's acceptable at the scale you're using.

This will produce a SQL query that looks something like this:

[...] ORDER BY ("Company"."id"='46128', "Company"."id"='2865', "Company"."id"='49569', [...])

Solution 4 - node.js

If you are using MySQL, you can use order by FIELD(id, ...) approach:

Company.findAll({
    where: {id : {$in : companyIds}},
    order: sequelize.literal("FIELD(company.id,"+companyIds.join(',')+")")
})

Keep in mind, it might be slow. But should be faster, than manual sorting with JS.

Solution 5 - node.js

May be a little late but want to mention an approach.
Sorting based on the [46128, 2865, 49569, 1488, 45600, 61991, 1418, 61919, 53326, 61680] can be done using ARRAY_POSITION function of postgreSQL.

const arr = [46128, 2865, 49569,  1488,   45600,   61991,  1418,  61919,   53326,   61680];
const ord = [sequelize.literal(`ARRAY_POSITION(ARRAY[${arr}]::integer[], "id")`)];

return Company.findAll({
    where: {
        id: arr
    },
    attributes: ['id', 'logo_version', 'logo_content_type', 'name', 'updated_at'],
    order: ord,
});

Solution 6 - node.js

I don't think this is possible in Sequelize's order clause, because as far as I can tell, those clauses are meant to be binary operations applicable to every element in your list. (This makes sense, too, as it's generally how sorting a list works.)

So, an order clause can do something like order a list by recursing over it asking "which of these 2 elements is older?" Whereas your ordering is not reducible to a binary operation (compare_bigger(1,2) => 2) but is just an arbitrary sequence (2,4,11,2,9,0).

When I hit this issue with findAll, here was my solution (sub in your returned results for numbers):

var numbers = [2, 20, 23, 9, 53];
var orderIWant = [2, 23, 20, 53, 9];
orderIWant.map(x => { return numbers.find(y => { return y === x })});

Which returns [2, 23, 20, 53, 9]. I don't think there's a better tradeoff we can make. You could iterate in place over your ordered ids with findOne, but then you're doing n queries when 1 will do.

Solution 7 - node.js

if required, databases order their output by the generic order of values in the order by fields.

if your order is not like this, you may add to the select an order_field, and give it a value based upon the value in id:

case 
when id=46128 then 0
when id=2865 then 1
when id=49569 then 2
end as order_field

and order by order_field.

if there are lots of values, you may stuff them in their original order in a temporary table with an identity primary key order_field, and inner join your select to that temporary table by your value field, ordering by order_field.

i don't know how to do this in sequelize, but found here answers on how it does things that i needed.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionPPSheinView Question on Stackoverflow
Solution 1 - node.jsJames111View Answer on Stackoverflow
Solution 2 - node.jsmeenalView Answer on Stackoverflow
Solution 3 - node.jsdrsView Answer on Stackoverflow
Solution 4 - node.jsPavlo RazumovskyiView Answer on Stackoverflow
Solution 5 - node.jsAgniveerView Answer on Stackoverflow
Solution 6 - node.jsAlex Moore-NiemiView Answer on Stackoverflow
Solution 7 - node.jsalexView Answer on Stackoverflow