【问题标题】:sequelize findAll sort order in nodejs在nodejs中续集findAll排序顺序
【发布时间】:2016-07-15 13:07:01
【问题描述】:

我正在尝试使用 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 也不是按名称排序的。请帮我解决一下。

【问题讨论】:

    标签: node.js express sequelize.js


    【解决方案1】:

    在 sequelize 中,您可以轻松添加 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() 承诺中收到对象后,您可能必须订购这些对象。查看这个关于根据自定义顺序对对象数组进行排序的问题:

    How do I sort an array of objects based on the ordering of another array?

    【讨论】:

    • 我想通过46128, 2865, 49569, 1488, 45600, 61991, 1418, 61919, 53326, 61680这样订购。
    • 嗯。你将无法做到这一点(据我所知)!在 .then() 承诺中收到对象后,您将不得不考虑对它们进行排序?为什么您需要在这个特定范围内订购它们?!有没有可以为你做的订单条款? @ppshein
    • 我尝试对与另一个关联的表执行相同操作,但没有成功。我们如何通过关联@james111 来做到这一点
    【解决方案2】:

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

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

    【讨论】:

      【解决方案3】:

      您可以使用以下代码以一种非常落后的方式完成此操作:

      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', [...])
      

      【讨论】:

        【解决方案4】:

        如果你使用的是MySQL,你可以使用order by FIELD(id, ...)approach

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

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

        【讨论】:

          【解决方案5】:

          可能有点晚了,但想提一个方法。
          可以使用 postgreSQL 的 ARRAY_POSITION 函数进行基于 [46128, 2865, 49569, 1488, 45600, 61991, 1418, 61919, 53326, 61680] 的排序。 p>

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

          【讨论】:

            【解决方案6】:

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

            因此,一个 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 次查询。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2012-11-07
              • 1970-01-01
              • 1970-01-01
              • 2021-12-18
              • 2018-06-01
              相关资源
              最近更新 更多