排序子集合和 Return 第一个子集合文档
Sort Subcollection and Return First Subcollection Document
我有一个包含如下文档的集合:
{
"_id": ObjectId("507f191e810c19729de860ea"),
"SubCollection": [{
"_id": ObjectId("55849c0002cee826cc67550a"),
"Timestamp": NumberLong(635717988841453845),
"IsValid": true
},
{
"_id": ObjectId("507f1f77bcf86cd799439011"),
"Timestamp": NumberLong(635717988830033174),
"IsValid": true
}]
}
public class RootEntity
{
public ObjectId Id { get; set; }
public List<SubEntity> SubCollection { get; set; }
}
public class SubEntity
{
public ObjectId Id { get; set; }
public long Timestamp { get; set; }
public bool IsValid { get; set; }
}
我需要创建一个 mongo 查询,returns 文档仅包含第一个子集合项。但是,子集合需要先通过 IsValid bool 进行筛选,然后通过 Timestamp 进行排序。
到目前为止,我有一个查询 returns 具有第一个子集合项的文档,但我无法让它首先对子集合进行排序,这可以实现吗?
这是我目前的查询,请注意我使用的是 C# .NET MongoDB Driver v2.0:
var filter = Builders<TestFocusEntity>.Filter.And(
Builders<RootEntity>.Filter.Eq(x => x.Id, id),
Builders<TestFocusEntity>.Filter.ElemMatch(x => x.SubCollection, sub => test.IsValid == true));
var result = await collection.Find(filter)
.Sort(Builders<RootEntity>.Sort.Ascending("SubCollection.$.Timestamp"))
.Project<RootEntity>(Builders<RootEntity>.Projection.Slice(x => x.SubCollection, 0, 1))
.ToListAsync();
var rootDocument = result.SingleOrDefault();
var subDocument = rootDocument == null
? null
: rootDocument.SubCollection.SingleOrDefault();
Timestamp 字段上的排序将对匹配的文档进行排序(这不会有任何效果,因为最多只有 1 个与 id 匹配)。它不会对匹配文档中的数组进行排序。在 MongoDB 中根本不可能在 DB 上的数组中进行这样的排序,这不是 C# 驱动程序的限制。
参见Mongo documentation数组排序:
With arrays ... an ascending sort compares the smallest element of arrays
即它按每个文档中数组的最小值对文档进行排序,而不是在数组内排序。
如果 SubEntity 数组相当小,您可以在拉回整个数组后在内存中执行这部分操作。
如果 SubEntity 数组非常大,您可能需要重新考虑文档架构以避免每次都将整个文档和子集合拉回到内存中。例如,使每个 SubEntity 成为一个独立的文档。
我有一个包含如下文档的集合:
{
"_id": ObjectId("507f191e810c19729de860ea"),
"SubCollection": [{
"_id": ObjectId("55849c0002cee826cc67550a"),
"Timestamp": NumberLong(635717988841453845),
"IsValid": true
},
{
"_id": ObjectId("507f1f77bcf86cd799439011"),
"Timestamp": NumberLong(635717988830033174),
"IsValid": true
}]
}
public class RootEntity
{
public ObjectId Id { get; set; }
public List<SubEntity> SubCollection { get; set; }
}
public class SubEntity
{
public ObjectId Id { get; set; }
public long Timestamp { get; set; }
public bool IsValid { get; set; }
}
我需要创建一个 mongo 查询,returns 文档仅包含第一个子集合项。但是,子集合需要先通过 IsValid bool 进行筛选,然后通过 Timestamp 进行排序。
到目前为止,我有一个查询 returns 具有第一个子集合项的文档,但我无法让它首先对子集合进行排序,这可以实现吗?
这是我目前的查询,请注意我使用的是 C# .NET MongoDB Driver v2.0:
var filter = Builders<TestFocusEntity>.Filter.And(
Builders<RootEntity>.Filter.Eq(x => x.Id, id),
Builders<TestFocusEntity>.Filter.ElemMatch(x => x.SubCollection, sub => test.IsValid == true));
var result = await collection.Find(filter)
.Sort(Builders<RootEntity>.Sort.Ascending("SubCollection.$.Timestamp"))
.Project<RootEntity>(Builders<RootEntity>.Projection.Slice(x => x.SubCollection, 0, 1))
.ToListAsync();
var rootDocument = result.SingleOrDefault();
var subDocument = rootDocument == null
? null
: rootDocument.SubCollection.SingleOrDefault();
Timestamp 字段上的排序将对匹配的文档进行排序(这不会有任何效果,因为最多只有 1 个与 id 匹配)。它不会对匹配文档中的数组进行排序。在 MongoDB 中根本不可能在 DB 上的数组中进行这样的排序,这不是 C# 驱动程序的限制。
参见Mongo documentation数组排序:
With arrays ... an ascending sort compares the smallest element of arrays
即它按每个文档中数组的最小值对文档进行排序,而不是在数组内排序。
如果 SubEntity 数组相当小,您可以在拉回整个数组后在内存中执行这部分操作。
如果 SubEntity 数组非常大,您可能需要重新考虑文档架构以避免每次都将整个文档和子集合拉回到内存中。例如,使每个 SubEntity 成为一个独立的文档。