web-dev-qa-db-fra.com

Comment trouver la valeur min dans mongodb

Comment faites-vous l'équivalent de

SELECT 
  MIN(Id) AS MinId
FROM
  Table

avec MongoDB?

Il semblerait que je devrai utiliser MapReduce mais je ne trouve aucun exemple qui montre comment procéder.

33
atbebtg

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 croissant (minimum-premier) sur le champ a, et nous ne renvoyons ensuite que 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.

61
dcrosta

La première

  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 également utiliser la fonction min comme celle-ci.

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

résultat sont

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

$ min est un opérateur d'accumulateur disponible uniquement dans la phase de groupe $.

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 n'est disponible que dans la phase de groupe $.

cliquez ici pour plus d'aide

12
wanghao

Je veux juste montrer comment cela peut être fait avec le pilote c # officiel (depuis la question sur mongodb csharp) avec une amélioration: je ne charge qu'un seul champ, mais pas le document entier si je veux juste trouver la valeur Min de ce champ. Voici un 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 classe:

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

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

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

Donc, le cas de test ci-dessus avec cette méthode d'extension peut être réécrit 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 l'utilisera;).

8
Andrew Orsich