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.
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.
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 $.
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;).