2011-06-15 12 views
31

Jak to zrobić równowartośćJak znaleźć wartość Min MongoDB

SELECT 
    MIN(Id) AS MinId 
FROM 
    Table 

w MongoDB. Wygląda na to, że będę musiał użyć MapReduce, ale nie mogę znaleźć żadnego przykładu pokazującego, jak to zrobić.

Dziękuję.

Odpowiedz

55

Można użyć kombinacji sort i limit naśladować 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}) jest rosnąco (minimum pierwszego) porządek na boisku a, a my tylko wtedy zwróci pierwszy dokument, który będzie być minimalną wartością dla tego pola.

EDIT: pamiętać, że jest napisany w powłoce Mongo, ale można zrobić to samo z C# lub w jakimkolwiek innym języku, stosując odpowiednie metody sterownika.

+5

Uwaga: prawdopodobnie będziesz chciał indeks na {a: 1} dla każdego dużego zbioru danych. –

+2

jest to nadal optymalny sposób uzyskania minimalnej wartości? – clifgray

+2

Możesz teraz użyć szkieletu Aggregate, aby osiągnąć ten wynik. Zobacz odpowiedź poniżej z wanghao. db.myCollection.aggregate ( [ { $ grupy: { _id {} minPrice {$ min "$ Cena"} } } ] ); – Waqas

8

Po prostu chcę pokazać, jak to zrobić z oficjalnym sterownikiem C# (od pytania o mongodb csharp) z jedną poprawką: ładuję tylko jedno pole, ale nie cały dokument, jeśli chcę po prostu znaleźć wartość Min tego pola. Oto kompletny przypadek testowy:

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

I Item klasa:

public class Item 
{ 
    public Item() 
    { 
    Id = ObjectId.GenerateNewId(); 
    } 

    [BsonId] 
    public ObjectId Id { get; set; } 
    public int IntValue { get; set; } 
    public string SomeOtherField { get; set; } 
} 

Aktualizacja: zawsze stara się przenieść dalej, tak, tutaj jest metoda rozbudowa do znalezienia wartości min w ciągu kolekcji:

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 
    } 
} 

Tak więc powyżej przypadku testowego z tą metodą rozszerzenia można przepisać w następujący sposób:

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

Mam nadzieję, że ktoś go użyje;).

+0

Dziękujemy! Właśnie napisałem kod dla sterownika C# – atbebtg

+0

@atbebtg: Nie ma za co. Zaledwie sekundę temu zaktualizowałem swoją odpowiedź, dlatego stworzyłem metodę rozszerzenia dla znalezienia minimalnej wartości;) –

+0

@Andred Orsich: Wow! Nie wiem, co jeszcze powiedzieć. Jeszcze raz Ci dziękuję! Nie martw się, na pewno skorzystam z tej funkcji :) – atbebtg

10

Pierwszy

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

Drugi, znaleźć wartość min

db.sales.aggregate(
    [ 
    { 
     $group: 
     { 
     _id: {}, 
     minPrice: { $min: "$price" } 
     } 
    } 
    ] 
); 

wynik jest

{ "_id" : { }, "minPrice" : 5 } 

Można również użyć funkcji min tak.

db.sales.aggregate(
    [ 
     { 
     $group: 
     { 
      _id: "$item", 
      minQuantity: { $min: "$quantity" } 
     } 
     } 
    ] 
) 

wynikiem są

{ "_id" : "xyz", "minQuantity" : 5 } 
{ "_id" : "jkl", "minQuantity" : 1 } 
{ "_id" : "abc", "minQuantity" : 2 } 

$ MIN operator akumulator tylko w etapie $ grupy.

UPDATE: Zmieniono w wersji 3.2: $ min jest dostępny w $ i $ grup projektowych etapach. W poprzednich wersjach MongoDB wartość $ min jest dostępna tylko w etapie grupy $.

click here for more help

+1

Fałsz: może być użyty w etapie '$ project'. Sprawdź dokument, do którego prowadzi łącze. – catalandres

Powiązane problemy