Как найти минимальное значение в mongodb - PullRequest
33 голосов
/ 15 июня 2011

Как вы делаете эквивалент

SELECT 
  MIN(Id) AS MinId
FROM
  Table

с MongoDB?

Похоже, мне придется использовать MapReduce, но я не могу найти пример, который показывает, как это сделатьэто.

Ответы [ 3 ]

61 голосов
/ 15 июня 2011

Вы можете использовать комбинацию 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,и тогда мы только возвращаем первый документ, который будет минимальным значением для этого поля.

РЕДАКТИРОВАТЬ: обратите внимание, что это написано в оболочке Монго, но вы можете сделать то же самоеиз C # или любого другого языка, используя соответствующие методы драйвера.

12 голосов
/ 10 октября 2015

Первое

  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") }
  ])

Второе, найдите минимальное значение

  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 - оператор накопителя, доступный только на групповой стадии $.

ОБНОВЛЕНИЕ: Изменено в версии 3.2: $ min доступен на этапах $ group и $ project.В предыдущих версиях MongoDB $ min был доступен только на групповом этапе.

Щелкните здесь для получения дополнительной помощи

8 голосов
/ 15 июня 2011

Просто хочу показать, как это можно сделать с помощью официального драйвера 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();
}

Надеюсь, кто-нибудь воспользуется им;).

...