改用聚合框架。 MongoDB LINQ 提供程序建立在它之上。
您可以通过以下查询获得按Id降序排列的每个组的10个项目:
db.items.aggregate([
{ "$sort": { "Id": -1 } },
{ "$group": { "_id": "$Category", "Items": { "$push": "$$ROOT" } } },
{ "$project": { "_id": 0, "GroupName": "$_id", "Items": { "$slice": ["$Items", 10] } } }
])
C#代码如下:
// models
public class Item
{
public string Id { get; set; }
public string Name { get; set; }
public string Category { get; set; }
}
public class ItemsGroup
{
public string GroupName { get; set; }
public Item[] Items { get; set; }
}
// query
var collection = db.GetCollection<Item>("Items");
IAggregateFluent<ItemsGroup> result = collection.Aggregate()
.SortByDescending(o => o.Id)
.Group(BsonDocument.Parse("{ _id: '$Category', Items: { '$push': '$$ROOT'}}"))
.Project<ItemsGroup>(BsonDocument.Parse("{ _id: 0, GroupName: '$_id', Items: { $slice: ['$Items', 10]}}"));
List<ItemsGroup> groups = result.ToList();
但是,此查询可能有问题。如果每个组有数千个项目,我猜小组赛会将它们全部保存在Items 临时数组中,而我们只需要 10 个。
如果被分组的键的数量不是很大,那么最好为每个组执行 $lookup 而不是将所有内容推入一个数组然后对其进行 $slicing。这可以通过以下查询来实现:
aggregate([
{ "$group": { "_id": "$Category" } },
{ "$lookup": {
"from": "Items",
"let": { "c": "$_id" },
"as": "Items"
"pipeline": [
{ "$match": { "$expr": { "$eq": ["$Category", "$$c"] } } },
{ "$sort": { "Id": -1 } },
{ "$limit": 10 }
],
}
},
{ "$project": { "_id": 0, "GroupName": "$_id", "Items": 1 } }
])
在 C# 代码中,它会是这样的:
BsonArray pipeline = new BsonArray
{
BsonDocument.Parse("{ $match: { $expr: { $eq: ['$Category', '$$c']} } }"),
BsonDocument.Parse("{ $sort: { Id: -1 } }"),
BsonDocument.Parse("{ $limit: 10 }")
};
BsonDocument lookup = new BsonDocument("$lookup",
new BsonDocument("from", "Items")
.Add("let", new BsonDocument("c", "$_id"))
.Add("pipeline", pipeline)
.Add("as", "Items")
);
IAggregateFluent<ItemsGroup> result = collection.Aggregate()
.Group(BsonDocument.Parse("{ _id: '$Category' }"))
.AppendStage<object>(lookup)
.Project<ItemsGroup>("{ _id: 0, GroupName: '$_id', Items: 1 }");
List<ItemsGroup> groups = result.ToList();