我正在尝试使用sequelize从数据库中输出所有对象列表,如下所示,并希望在where子句中添加id时对数据进行排序。
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 也不按名称排序。请帮我解决一下。
在续集中,您可以轻松添加 order by 子句。
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()
承诺范围内收到物品后,您可能需要订购这些物品。查看有关根据自定义顺序对对象数组进行排序的问题:
如果您想根据特定列以升序或降序对数据进行排序,请使用
sequlize js
,请使用 order
的 sequlize
方法,如下所示
// Will order the specified column by descending order
order: sequelize.literal('column_name order')
e.g. order: sequelize.literal('timestamp DESC')
如果您使用MySQL,您可以使用
order by FIELD(id, ...)
方法:
Company.findAll({
where: {id : {$in : companyIds}},
order: sequelize.literal("FIELD(company.id,"+companyIds.join(',')+")")
})
请记住,它可能会很慢。但应该比用 JS 手动排序更快。
您可以使用以下代码以非常间接的方式完成此操作:
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', [...])
可能有点晚了,但想提一下方法。
基于[46128, 2865, 49569, 1488, 45600, 61991, 1418, 61919, 53326, 61680]的排序可以使用postgreSQL的ARRAY_POSITION函数完成。
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,
});
我认为这在 Sequelize 的 order 子句中是不可能的,因为据我所知,这些子句意味着适用于列表中每个元素的二元运算。 (这也是有道理的,因为这通常是对列表进行排序的工作方式。)
因此,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 个查询。
如果您的订单不是这样,您可以在 select 中添加一个 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 的临时表中,并通过值字段将您的选择内部连接到该临时表,按 order_field 排序。我不知道如何在续集中执行此操作,但在这里找到了有关它如何执行我需要的操作的答案。
“”引号为我工作。
用于调试 您可以查看由sequelize 生成的查询是什么,然后尝试在特定的数据库控制台上运行它。
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;
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")`)];