Comment trouver la valeur min en mongodb

Comment faire l'équivalent de

SELECT 
  MIN(Id) AS MinId
FROM
  Table

en MongoDB. Il semble que je vais devoir utiliser MapReduce mais je ne trouve aucun exemple qui montrent comment faire cela.

je vous Remercie.

32
demandé sur Andrew Orsich 2011-06-15 19:43:32

3 réponses

Vous pouvez utiliser une combinaison de sort et limit pour émuler 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}) est un Tri ascendant (minimum-premier) sur le a champ, et ensuite nous retourner uniquement le premier document, qui sera la valeur minimale pour ce champ.

EDIT: notez que ceci est écrit dans le shell mongo, mais vous pouvez faire la même chose depuis C# ou tout autre langage en utilisant les méthodes de pilote appropriées.

58
répondu dcrosta 2011-06-15 15:51:15

Le premier

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

la seconde, trouver la valeur min

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

le résultat est

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

vous pouvez aussi utiliser la fonction min comme celle-ci.

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

résultat

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

$ min est un opérateur d'accumulateur disponible seulement dans l'étape $group.

mise à jour: Modifié dans la version 3.2: $min est disponible dans les étapes $group et $project. Dans les versions précédentes de MongoDB, $min is disponible dans l' $en phase de groupe seulement.

Cliquez ici pour plus d'aide

9
répondu wanghao 2016-08-09 21:57:58

je veux juste montrer comment cela peut être fait avec le pilote officiel c# (depuis la question sur mongodb csharp) avec une amélioration: je charge seulement un champ, mais pas le document entier si je veux juste trouver la valeur Min de ce champ. Voici le cas de test complet:

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

Et Item catégorie :

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

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

mise à Jour: toujours essayer d'aller plus loin, donc, voici la méthode d'extension pour trouver la valeur min dans la 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
    }
}

Si le test ci-dessus case avec cette méthode d'extension peut être rewrité comme ceci:

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

j'Espère que quelqu'un va l'utiliser ;).

8
répondu Andrew Orsich 2011-06-15 17:12:07