在 nodejs 中对 findAll 排序顺序进行序列化

我试图输出所有的对象列表从数据库与序列如下,并希望得到的数据被排序,因为我添加了 id 在 where 子句。

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']
});
};

但是问题是在渲染之后,所有的数据按照如下方式进行排序。

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

正如我所发现的,它既不按 ID 也不按名称排序。请帮助我如何解决它。

219662 次浏览

在序列化中,您可以很容易地通过子句添加顺序。

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']
});
};

看到我是如何添加对象的 order数组的了吗?

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

编辑:

您可能必须订购的对象,一旦他们已经收到内部的 .then()承诺。看看这个关于基于自定义顺序排列对象数组的问题:

如何根据另一个数组的顺序对一个对象数组进行排序?

我认为这在 Sequelize 顺序子句中是不可能的,因为据我所知,这些子句是适用于列表中每个元素的二进制操作。(这也是有道理的,因为这通常是对列表进行排序的方式。)

因此,order 子句可以通过递归地询问“这两个元素中哪一个更老?”来对列表进行排序然而,你的排序不能简化为一个二元运算(compare_bigger(1,2) => 2) ,而只是一个任意的序列(2,4,11,2,9,0)。

当我遇到 findAll的这个问题时,以下是我的解决方案(请在返回的 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 })});

返回 [2, 23, 20, 53, 9]。我觉得没有比这更好的交易了。您可以使用 findOne在已排序的 id 上进行迭代,但是当1执行时,您将执行 n 个查询。

你可以通过下面的代码用一种非常隐晦的方式来实现这一点:

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')
});
};

这是有限的,因为它的性能特征非常糟糕,超过几十个记录,但它是可以接受的规模,您正在使用。

这将产生一个 SQL 查询,它看起来像这样:

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

如果你正在使用 MySQL,你可以使用 order by FIELD(id, ...) 接近:

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

请记住,它可能比较慢,但应该比用 JS 手动排序更快。

如果希望根据特定列按升序或降序对数据进行排序,请使用 sequlize js,使用 sequlizeorder方法,如下所示

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

可能有点晚了,但我想提一个方法。
利用 < strong > postgreSQL 的 ARRAY _ POSITION 函数,可以实现基于[46128,2865,49569,1488,45600,61991,1418,61919,53326,61680]的排序。

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,
});

如果需要,数据库按字段顺序中的通用值顺序对输出进行排序。

如果您的顺序不是这样,您可以添加到 select an order _ field,并根据 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.

如果有很多值,您可以将它们按照原始顺序填充到一个具有标识主键 order _ field 的临时表中,然后在内部通过 value 字段将 select 加入到该临时表中,通过 order _ field 进行排序。

我不知道如何做到这一点在序列,但在这里找到答案,它如何做的事情,我需要的。

通过使用围绕属性名称的 “引用”对我有效。
对于 Debug ,您可以看到通过 Sequelize 生成的查询是什么,然后尝试在特定的 DB 控制台上运行它。

在 My Case 中,我无法按照上一个 updatedAt列对数据进行排序
代码片段:

exports.readAll = (req, res) => {
console.log("Inside ReadAll Data method");
let data;
if (!req.body) {
data = CompanyModel.findAll({  order: [[sequelize.literal('"updatedAt"'), 'DESC']]});
} else {
data = CompanyModel.findAll({  order: [[sequelize.literal('"updatedAt"'), 'DESC']]});
}
data
.then((data) => {
res.send(
data
);
})
.catch((err) => {
res.status(500).send({
message: err.message || "Some error occurred while retrieving data.",
});
});
};

在我的例子中形成 SQL 查询:

Inside ReadAll Data method


Executing (default): SELECT "company_name", "company_id", "on_record", "createdAt", "updatedAt" FROM "companies" AS "company" ORDER BY "updatedAt" DESC;

如果有人使用 uuid 类型,请使用上面@Agniveer 修改过的示例

const ids = [
'f01a057e-5646-4527-a219-336804317246',
'ee900087-4910-42b4-a559-06aea7b4e250',
'b363f116-1fc5-473a-aed7-0ceea9beb14d'
];


const idsFormat = `'${ids.join("','")}'`;


const order = [sequelize.literal(`ARRAY_POSITION(ARRAY[${idsFormat}]::uuid[], "<insert_table_name>"."id")`)];