【问题标题】:How to find longest and shortest length of a value for a field in mongoDb?如何在mongoDb中找到一个字段的最长和最短长度?
【发布时间】:2014-12-11 06:57:40
【问题描述】:

字段的数据类型是字符串。我想在 mongoDB 中找到一个字段的最长和最短值的长度。

我的收藏中总共有 500000 个文档。

【问题讨论】:

    标签: javascript mongodb mapreduce mongodb-query mongoid


    【解决方案1】:

    您可以使用 mongo shell 脚本。请注意,它将执行全表扫描。

        function findMinMax() {
            var max = 0;
            var min = db.collection.findOne().fieldName.length;
    
            db.collection.find().forEach(function(doc) {
                var currentLength = doc.fieldName.length; 
                if (currentLength > max) {
                   max = currentLength;
                }
                if (currentLength < min) {
                   min = currentLength;
                }
            });
    
             print(max);
             print(min);
        }
    
       use <databaseName>
       findMinMax();
    

    您可以将函数保存在一个文件中,例如 c:\minMax.js 并运行该文件,

    c:\mongodb\bin> mongo dbName < c:\minMax.js
    

    注意:您可能需要提供必要的主机名、用户名、密码才能连接到您的数据库。

    c:\mongodb\bin> mongo --host hostName --port portNumber -u userName -p password dbName < c:\minMax.js
    

    【讨论】:

    • 如何将其作为 mongo shell 脚本运行?
    • 所以当我将函数保存为 minMax.js 时,我应该用 db..find().forEach( function(doc)?我是否也应该在这里使用 给我的数据库名称?
    • 我扩展了这个答案并将其分享到 github cf。 github.com/boly38/mongo-scripts
    【解决方案2】:

    在现代版本中,MongoDB 具有 $strLenBytes$strLenCP 聚合运算符,您可以这样做:

    Class.collection.aggregate([
      { "$group" => {
        "_id" => nil,
        "max" => { "$max" => { "$strLenCP" => "$a" } },
        "min" => { "$min" => { "$strLenCP" => "$a" } }
      }}
    ]) 
    

    "a" 是您想要从中获取最小和最大长度的文档中的字符串属性。


    要输出最小和最大长度,最好的方法是使用 mapReduce 并通过一些技巧来保持值。

    首先,您定义一个映射器函数,该函数实际上只是要从您的集合中输出单个项目以减少负载:

    map = Q%{
        function () {
    
          if ( this.a.length < store[0] )
            store[0] = this.a.length;
    
          if ( this.a.length > store[1] )
            store[1] = this.a.length;
    
          if ( count == 0 )
            emit( null, 0 );
    
          count++;
    
        }
    }
    

    由于这主要使用全局范围的变量来保持最小和最大长度,因此您只想在发出的单个文档的 finalize 函数中替换它。没有 reduce 阶段,但为此定义一个“空白”函数,即使它没有被调用:

    reduce = Q%{ function() {} }
    
    finalize = Q%{
        function(key,value) {
            return {
                min: store[0],
                max: store[1]
            };
        }
    }
    

    然后调用mapReduce操作:

    Class.map_reduce(map,reduce).out(inline: 1).finalize(finalize).scope(store: [], count: 0)
    

    所以所有工作都在服务器上完成,而不是通过迭代发送到客户端应用程序的结果。在这样的一个小场景中:

    { "_id" : ObjectId("543e8ee7ddd272814f919472"), "a" : "this" }
    { "_id" : ObjectId("543e8eedddd272814f919473"), "a" : "something" }
    { "_id" : ObjectId("543e8ef6ddd272814f919474"), "a" : "other" }
    

    你会得到这样的结果(shell 输出,但对于驱动程序几乎相同):

    {
        "results" : [
                {
                        "_id" : null,
                        "value" : {
                                "min" : 4,
                                "max" : 9
                        }
                }
        ],
        "timeMillis" : 1,
        "counts" : {
                "input" : 3,
                "emit" : 1,
                "reduce" : 0,
                "output" : 1
        },
        "ok" : 1
    }
    

    因此,mapReduce 允许服务器上的 JavaScript 处理相当快地完成此操作,从而减少您的网络流量。 MongoDB目前没有其他原生方式返回字符串长度,因此需要在服务器端进行JavaScript处理。

    【讨论】:

    • @muistooshort 为什么要发出 500000 个文档更重要。 OP 只想要最小值和最大值。全局是 JavaScript 声明的,并且是这样转换的。并且只有 mapReduce 函数可以访问。够清楚吗?
    • @muistooshort MongoDB 没有任何其他运算符来返回字符串的长度,因此您需要 JavaScript,而 mapReduce 是“返回”结果的唯一方法。如果有一些原生的东西可能会更好,但这仍然是一个文档值与另一个文档值的“全局”比较,同样,mapReduce 是唯一提供此功能的东西。在 reducer 上敲打 500,000 个文档来完成可以在 mapper 中完成的工作将是一种 hack 和不必要的,更不用说更多的工作了。引用的 JavaScript 中没有内部字符串,所以这并不重要。
    • 或者对于新的 mongos,你应该使用 ":" 而不是 "=>" 和 "null" 而不是 "nil"。加上 db.collections...
    • @AntonLosev 这是使用=&gt;nil 的“Ruby”,由问题上的mongoid 标签引用。因此,Q% 的事情也是 mapreduce 示例从“Ruby”代码在服务器上执行 JavaScript。所以这就是你错过的。
    • 知道了,很容易错过)
    【解决方案3】:

    用于获取字段的最长值

    db.entities.aggregate([{ $match:{ condition   }  },{
      $addFields: {
        "length": { $strLenCP: "$feildName" }
      }},
    { "$sort": { "length": -1 } },
    {$limit:1}
    ])
    

    将 { "$sort": { "length": -1 } } 更改为 { "$sort": { "length": 1 } } 以获得字段的最短值

    【讨论】:

      猜你喜欢
      • 2011-03-20
      • 2021-03-18
      • 2013-05-08
      • 1970-01-01
      • 2021-09-27
      • 2021-10-28
      • 1970-01-01
      • 2023-03-10
      • 1970-01-01
      相关资源
      最近更新 更多