How to find longest and shortest length of a value for a field in mongoDb?

In modern releases MongoDB has the $strLenBytes or $strLenCP aggregation operators than allow you to simply do:

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

Where "a" is the string property in your document you want to get the min and max length from.


To output the minimum and maximum length, the best approach available is to use mapReduce with a few tricks to just keep the values.

First you define a mapper function which is just really going to output a single item from your collection to reduce the load:

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++;

    }
}

Since this is working mostly with a globally scoped variable keeping the min and max lengths you just want to substitute this in a finalize function on the single document emitted. There is no reduce stage, but define a "blank" function for this even though it is not called:

reduce = Q%{ function() {} }

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

Then call the mapReduce operation:

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

So all the work is done on the server and not by iterating results sent to the client application. On a small set like this:

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

You get a result like this (shell output, but much the same for the driver ):

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

So mapReduce allows the JavaScript processing on the server to do this fairly quickly, reducing your network traffic. There is no other native way at present for MongoDB to return a string length right now, so the JavaScript processing is necessary on the server.


For getting the longest value for a field

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

Change the { "$sort": { "length": -1 } } to { "$sort": { "length": 1 } } for the shortest value for a field


You can use a mongo shell script. Note that it will perform a full table scan.

    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();

You can save the function in a file say c:\minMax.js and run the file as,

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

Note: you may need to supply the necessary hostname, user name, password to connect to your database.

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