问题描述
|
你如何做相当于
SELECT
MIN(Id) AS MinId
FROM
Table
与MongoDB?
看来我将不得不使用MapReduce,但是我找不到任何显示该操作方法的示例。
解决方法
您可以结合使用
sort
和limit
来模拟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})
是a
字段上的升序(最小优先)排序,然后我们仅返回第一个文档,该文档将是该字段的最小值。
编辑:请注意,这是用mongo shell编写的,但是您可以使用适当的驱动程序方法从C#或任何其他语言中执行相同的操作。
, 首先
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,\"quantity\" : 10,\"date\" : ISODate(\"2014-02-15T08:00:00Z\") },{ \"_id\" : 5,\"date\" : ISODate(\"2014-02-15T09:05:00Z\") }
])
第二,找到最小值
db.sales.aggregate(
[
{
$group:
{
_id: {},minPrice: { $min: \"$price\" }
}
}
]
);
结果是
{ \"_id\" : { },\"minPrice\" : 5 }
您也可以像这样使用min函数。
db.sales.aggregate(
[
{
$group:
{
_id: \"$item\",minQuantity: { $min: \"$quantity\" }
}
}
]
)
结果是
{ \"_id\" : \"xyz\",\"minQuantity\" : 5 }
{ \"_id\" : \"jkl\",\"minQuantity\" : 1 }
{ \"_id\" : \"abc\",\"minQuantity\" : 2 }
$ min是累加器运算符,仅在$ group阶段可用。
更新:
在版本3.2中更改:$ min在$ group和$ project阶段可用。在以前的MongoDB版本中,$ min仅在$ group阶段可用。
点击这里获得更多帮助
, 只是想展示如何使用正式的c#驱动程序(由于有关mongodb csharp的问题)可以完成一项改进:我只加载一个字段,但是如果我只想查找该字段的Min值,则不加载整个文档。这是完整的测试用例:
[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();
}
和Item
类:
public class Item
{
public Item()
{
Id = ObjectId.GenerateNewId();
}
[BsonId]
public ObjectId Id { get; set; }
public int IntValue { get; set; }
public string SomeOtherField { get; set; }
}
更新:始终尝试进一步,因此,这里是在集合中查找最小值的扩展方法:
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
}
}
因此,使用这种扩展方法的上述测试用例可以这样重写:
[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();
}
希望有人会使用它;)。