Sequelize如何添加自定义排序功能?

ave*_*123 5 javascript node.js sequelize.js

我有一个带有字符串列“grades”的表,其中包含以下内容['uni', '9','10',11','12'].我无法将此列更改为 Int。

我有以下排序代码:

Course.findAll({
  order: [
    ['grade', 'ASC']
  ],
...
Run Code Online (Sandbox Code Playgroud)

但按年级排序会给我以下顺序:

['10','11', '12', '9', 'uni' ]

显然我不希望它按这个顺序排列。我查看了 Sequelize 文档,他们似乎有一种方法可以提交用于排序的自定义函数,但我没有一个示例来说明它的样子:

// Will order by  otherfunction(`col1`, 12, 'lalala') DESC
[sequelize.fn('otherfunction', sequelize.col('col1'), 12, 'lalala'), 'DESC'],
Run Code Online (Sandbox Code Playgroud)

https://sequelize.org/master/manual/model-querying-basics.html#ordering-and-grouping

有谁知道执行此操作的方法?

yar*_*nsn 1

文档确实有点含糊,我只能假设otherfunction它们是指方言(mssql / mysql等)支持的任何其他功能及其所需的参数,但尚未测试此假设。

但是,我找到了一种解决方法,使用sequelize.literal

const customOrder = (column, values, direction) => {
  let orderByClause = 'CASE ';

  for (let index = 0; index < values.length; index++) {
    let value = values[index];

    if (typeof value === 'string') value = `'${value}'`;

    orderByClause += `WHEN ${column} = ${value} THEN '${index}' `;
  }

  orderByClause += `ELSE ${column} END`

  return [Sequelize.literal(orderByClause), direction]
};
Run Code Online (Sandbox Code Playgroud)

请注意,索引不会保留为 int,而是被视为字符串,这是因为此列中的其余值都是字符串,并且当落在链外时将按此顺序排序CASE WHEN

你使用它的方式是:

Course.findAll({
  order: [
    customOrder('grade', ['uni', '9','10','11','12'], 'ASC')
  ],
...
Run Code Online (Sandbox Code Playgroud)

此代码采用一个值数组(按所需顺序排序),并将它们添加到一个CASE子句中,为每个值提供各自的索引,该索引决定顺序。因此,考虑到上面的值,您最终会得到:

  FROM
    ...
  WHERE
    ...
  ORDER BY CASE WHEN grade = 'uni' THEN '0'
                WHEN grade = '9' THEN '1'
                WHEN grade = '10' THEN '2'
                WHEN grade = '11' THEN '3'
                WHEN grade = '12' THEN '4'
                ELSE grade END ASC
Run Code Online (Sandbox Code Playgroud)

作为参考,我使用了这篇博文本期票证