How to find min value in mongodb
You can use a combination of sort
and limit
to emulate min
:
> db.foo.insert({a: 1})> db.foo.insert({a: 2})> db.foo.insert({a: 3})> db.foo.find().sort({a: 1}).limit(1) { "_id" : ObjectId("4df8d4a5957c623adae2ab7e"), "a" : 1 }
sort({a: 1})
is an ascending (minimum-first) sort on the a
field, and we then only return the first document, which will be the minimum value for that field.
EDIT: note that this is written in the mongo shell, but you can do the same thing from C# or any other language using the appropriate driver methods.
The first
db.sales.insert([ { "_id" : 1, "item" : "abc", "price" : 10, "quantity" : 2, "date" : ISODate("2014-01-01T08:00:00Z") }, { "_id" : 2, "item" : "jkl", "price" : 20, "quantity" : 1, "date" : ISODate("2014-02-03T09:00:00Z") }, { "_id" : 3, "item" : "xyz", "price" : 5, "quantity" : 5, "date" : ISODate("2014-02-03T09:05:00Z") }, { "_id" : 4, "item" : "abc", "price" : 10, "quantity" : 10, "date" : ISODate("2014-02-15T08:00:00Z") }, { "_id" : 5, "item" : "xyz", "price" : 5, "quantity" : 10, "date" : ISODate("2014-02-15T09:05:00Z") } ])
The second, find the min value
db.sales.aggregate( [ { $group: { _id: {}, minPrice: { $min: "$price" } } } ] );
result is
{ "_id" : { }, "minPrice" : 5 }
You can also use min function like this.
db.sales.aggregate( [ { $group: { _id: "$item", minQuantity: { $min: "$quantity" } } } ] )
result are
{ "_id" : "xyz", "minQuantity" : 5 }{ "_id" : "jkl", "minQuantity" : 1 }{ "_id" : "abc", "minQuantity" : 2 }
$min is an accumulator operator available only in the $group stage.
UPDATE:Changed in version 3.2: $min is available in the $group and $project stages. In previous versions of MongoDB, $min is available in the $group stage only.
Just want to show how it can be done with official c# driver (since question about mongodb csharp) with one improvement: I am loading only one field, but not entire document if i want just find Min value of that field. Here is complete test case:
[TestMethod]public void Test(){ var _mongoServer = MongoServer.Create("mongodb://localhost:27020"); var database = _mongoServer.GetDatabase("StackoverflowExamples"); var col = database.GetCollection("items"); //Add test data col.Insert(new Item() { IntValue = 1, SomeOtherField = "Test" }); col.Insert(new Item() { IntValue = 2 }); col.Insert(new Item() { IntValue = 3 }); col.Insert(new Item() { IntValue = 4 }); var item = col.FindAs<Item>(Query.And()) .SetSortOrder(SortBy.Ascending("IntValue")) .SetLimit(1) .SetFields("IntValue") //here i loading only field that i need .Single(); var minValue = item.IntValue; //Check that we found min value of IntValue field Assert.AreEqual(1, minValue); //Check that other fields are null in the document Assert.IsNull(item.SomeOtherField); col.RemoveAll();}
And Item
class :
public class Item{ public Item() { Id = ObjectId.GenerateNewId(); } [BsonId] public ObjectId Id { get; set; } public int IntValue { get; set; } public string SomeOtherField { get; set; }}
Update: Always trying to move further, so, here is extention method for finding min value within collection:
public static class MongodbExtentions{ public static int FindMinValue(this MongoCollection collection, string fieldName) { var cursor = collection.FindAs<BsonDocument>(Query.And()) .SetSortOrder(SortBy.Ascending(fieldName)) .SetLimit(1) .SetFields(fieldName); var totalItemsCount = cursor.Count(); if (totalItemsCount == 0) throw new Exception("Collection is empty"); var item = cursor.Single(); if (!item.Contains(fieldName)) throw new Exception(String.Format("Field '{0}' can't be find within '{1}' collection", fieldName, collection.Name)); return item.GetValue(fieldName).AsInt32; // here we can also check for if it can be parsed }}
So above test case with this extention method can be rewrited like this:
[TestMethod]public void Test(){ var _mongoServer = MongoServer.Create("mongodb://localhost:27020"); var database = _mongoServer.GetDatabase("StackoverflowExamples"); var col = database.GetCollection("items"); var minValue = col.FindMinValue("IntValue"); Assert.AreEqual(1, minValue); col.RemoveAll();}
Hope someone will use it ;).