使用 C# SDK 投影到另一种类型
Projecting to another type using the C# SDK
我希望能够在使用 C# SDK 查询 MongoDB 时投影到 另一种 类型。
例如,下面我想使用 MyType
、 的构建器过滤器(或 LINQ 表达式)查询集合,但 我想将结果投影到 MySubType
.
var mySubTypes = Database
.GetCollection<MyType>("MyCollection")
.Find(Builders<MyType>.Filter.AnyIn(x => x.Documents, documentId))
.ProjectTo<MySubType>() // Project to another type??
.ToList();
可以想象 MySubType
是 MyType
的子集,使用继承表示:
public class MyType : MySubType
{
[BsonElement("documents")]
public List<string> Documents { get; set; }
}
public class MySubType
{
[BsonElement("name")]
public string Name { get; set; }
}
我为什么要这样做?
因为 Documents
数组非常大,仅在数据库引擎内查询(即过滤)期间使用。检索和序列化此数组将是不必要的成本。
我找到了你想要的执行映射的方法:
collection
.Find(Builders<MyType>.Filter.AnyIn(x => x.Documents, new[] { "c" }))
.Project(Builders<MyType>.Projection.Exclude(c => c.Documents))
.As<MySubType>()
.ToList();
但首先您应该为您的 SubType 注册映射并忽略额外的元素。我不是 100% 理解它,似乎是驱动程序的一个错误,它没有从 mongo 得到 Documents
,但知道 MyType
有这样的 属性.请注意,您应该注册您的 class 映射, 在 您首先创建此类型的集合之前。
if (!BsonClassMap.IsClassMapRegistered(typeof(MySubType)))
{
BsonClassMap.RegisterClassMap<MySubType>(cm =>
{
cm.AutoMap();
cm.SetIgnoreExtraElements(true);
});
}
我用样本数据做的:
var toInsert = new List<MyType>
{
new MyType {Id = 1, Name = "bla", Documents =new List<string> {"a", "b", "v"}},
new MyType {Id = 2, Name = "ada", Documents =new List<string> {"c", "d", "r"}},
};
并且可以获得预期的输出:
collection
.Find(Builders<MyType>.Filter.AnyIn(x => x.Documents, new[] { "c" }))
.Project(Builders<MyType>.Projection.Exclude(c => c.Documents))
.As<MySubType>()
.ToList()
.Dump();
我希望能够在使用 C# SDK 查询 MongoDB 时投影到 另一种 类型。
例如,下面我想使用 MyType
、 的构建器过滤器(或 LINQ 表达式)查询集合,但 我想将结果投影到 MySubType
.
var mySubTypes = Database
.GetCollection<MyType>("MyCollection")
.Find(Builders<MyType>.Filter.AnyIn(x => x.Documents, documentId))
.ProjectTo<MySubType>() // Project to another type??
.ToList();
可以想象 MySubType
是 MyType
的子集,使用继承表示:
public class MyType : MySubType
{
[BsonElement("documents")]
public List<string> Documents { get; set; }
}
public class MySubType
{
[BsonElement("name")]
public string Name { get; set; }
}
我为什么要这样做?
因为 Documents
数组非常大,仅在数据库引擎内查询(即过滤)期间使用。检索和序列化此数组将是不必要的成本。
我找到了你想要的执行映射的方法:
collection
.Find(Builders<MyType>.Filter.AnyIn(x => x.Documents, new[] { "c" }))
.Project(Builders<MyType>.Projection.Exclude(c => c.Documents))
.As<MySubType>()
.ToList();
但首先您应该为您的 SubType 注册映射并忽略额外的元素。我不是 100% 理解它,似乎是驱动程序的一个错误,它没有从 mongo 得到 Documents
,但知道 MyType
有这样的 属性.请注意,您应该注册您的 class 映射, 在 您首先创建此类型的集合之前。
if (!BsonClassMap.IsClassMapRegistered(typeof(MySubType)))
{
BsonClassMap.RegisterClassMap<MySubType>(cm =>
{
cm.AutoMap();
cm.SetIgnoreExtraElements(true);
});
}
我用样本数据做的:
var toInsert = new List<MyType>
{
new MyType {Id = 1, Name = "bla", Documents =new List<string> {"a", "b", "v"}},
new MyType {Id = 2, Name = "ada", Documents =new List<string> {"c", "d", "r"}},
};
并且可以获得预期的输出:
collection
.Find(Builders<MyType>.Filter.AnyIn(x => x.Documents, new[] { "c" }))
.Project(Builders<MyType>.Projection.Exclude(c => c.Documents))
.As<MySubType>()
.ToList()
.Dump();