【问题标题】:Sort descending String with Number in Mongo DB在Mongodb中使用数字对降序字符串进行排序
【发布时间】:2015-12-13 19:02:34
【问题描述】:

我目前有一个包含两个字段的数据库。对于这个问题,只有其中一个很重要。

想象一个带有单个字符串字段(我们称之为“标签”)的数据库,以及以下模式:[a-z]*[0-9]*,例如:

  • test129
  • test130
  • 一些43
  • some44
  • 一些45
  • ...

我的应用程序需要生成新的“标签”,给定前置“标识符”(如 testsome)。

假设我输入test 作为前置名称,100 作为要生成的“标签”的数量。

  • 他找到了带有前缀名称 test 的 LAST 标记。
  • 解析前缀名称后的数字。
  • 对该数字加1,并生成100个带有该序列的标签。

在这种特定情况下,输出将是:test131test132、...、test230

我实现了这个,它与Mongoose 一起工作得很好。然而,当我试图从一个已经存在的超过 1000 个的 Tag 中生成一个“Tag”时,我发现第一步是一个缺陷。它正在返回,比如说 test999 而不是 test1200,并导致迭代从 999 开始,并且由于它需要是唯一的而出现错误。

这是因为,对字符串进行排序不同于对数字进行排序。我知道这个问题,但我怎样才能以简单的方式解决这个问题,而无需创建额外的字段?

更新:我找到标签的部分代码:

   lastAliasNumber: function (next){
        console.log('process.lastAliasNumber');

        // Skip if prefix is not set (tags already have name)
        if(!prefix) return next();

        // Build RegExp to find tags with the prefix given
        var regexp = new RegExp('^'+prefix+'[0-9]+$', 'i');

        Models.Tag
            .findOne()
            .where({
                alias: regexp
            })
            .sort('-alias')
            .exec(function (err, tag){
                if(err) return next(err);

                // Remove prefix and try parsing number
                var lastId = 100;

                if(tag){
                    // Remove prefix
                    var number = tag.alias.toLowerCase().replace(prefix, '');

                    // Get number from it
                    number = parseInt(number);
                    if(number) lastId = number;
                }
                console.log('lastAliasNumber', lastId);
                next(null, lastId);
            });
    },

【问题讨论】:

  • 为什么标签大于 1000 是个问题?为什么会返回 999?
  • @YuriZarubin,如果你对test999, test1000进行降序排序,你会发现test999排在第一位,虽然test1000更高。那是因为91 排在前,长度无所谓
  • 对,我就是这么想的。我的意思是,这个问题不只是超过 1000 的数字,这听起来就像你在说的那样。
  • 你能显示你的mongoose/mongo查询代码吗?
  • 我以 1000 为例,但它发生在每个 10^x 标签... 将更新我的帖子

标签: node.js mongodb sorting mongoose database


【解决方案1】:

在 MongoDB 中没有现成的方法来进行这种排序。由于你的字段是字符串字段,会按照字符串排序规则进行排序,无法对一个字段进行变量类型排序。

您最好的选择(假设您不能简单地使用整数类型并希望只保留一个字段)是计算出理论上的最大条目数并相应地用相关的前导数 0 填充您的字符串。

EG。假设您的字符串最多有 1,000,000 个条目:

test000999
test001200
test000131

另一种选择是让这些条目成为具有两种不同数据类型的完整子文档。

考虑下面我的快速示例文档

> db.bar.insert({x:{text:"test",num:1}})
WriteResult({ "nInserted" : 1 })
> db.bar.insert({x:{text:"test",num:100}})
WriteResult({ "nInserted" : 1 })
> db.bar.insert({x:{text:"test",num:2}})
WriteResult({ "nInserted" : 1 })
> db.bar.insert({x:{text:"sweet",num:2}})
WriteResult({ "nInserted" : 1 })
> db.bar.insert({x:{text:"sweet",num:1}})
WriteResult({ "nInserted" : 1 })
> db.bar.find().sort({x:1})
{ "_id" : ObjectId("55fa469d695632545d3aff1f"), "x" : { "text" : "sweet", "num" : 1 } }
{ "_id" : ObjectId("55fa469b695632545d3aff1e"), "x" : { "text" : "sweet", "num" : 2 } }
{ "_id" : ObjectId("55fa468a695632545d3aff1b"), "x" : { "text" : "test", "num" : 1 } }
{ "_id" : ObjectId("55fa4695695632545d3aff1d"), "x" : { "text" : "test", "num" : 2 } }
{ "_id" : ObjectId("55fa468f695632545d3aff1c"), "x" : { "text" : "test", "num" : 100 } }
> db.bar.find().sort({x:-1})
{ "_id" : ObjectId("55fa468f695632545d3aff1c"), "x" : { "text" : "test", "num" : 100 } }
{ "_id" : ObjectId("55fa4695695632545d3aff1d"), "x" : { "text" : "test", "num" : 2 } }
{ "_id" : ObjectId("55fa468a695632545d3aff1b"), "x" : { "text" : "test", "num" : 1 } }
{ "_id" : ObjectId("55fa469b695632545d3aff1e"), "x" : { "text" : "sweet", "num" : 2 } }
{ "_id" : ObjectId("55fa469d695632545d3aff1f"), "x" : { "text" : "sweet", "num" : 1 } }

【讨论】:

    猜你喜欢
    • 2013-06-05
    • 2017-01-09
    • 1970-01-01
    • 1970-01-01
    • 2020-09-16
    • 2015-09-21
    • 2017-08-11
    • 2019-04-09
    • 2017-03-04
    相关资源
    最近更新 更多