【发布时间】:2021-06-14 15:18:51
【问题描述】:
我有一个这样的域类。
public class Thing
{
public Guid Id { get; set; }
public string Name { get; set; }
public Dictionary<string, string> Stuff { get; set; }
}
我正在使用以下方法从我的数据库中检索它。
return await _db.Things
.Find(x => x.Name == name)
.SingleOrDefaultAsync(token);
我注意到,可能有大量不必要的数据,所以我使用了这样的投影。
ProjectionDefinition<Thing> projection = Builders<Thing>
.Projection
.Include(a => a.Id)
.Include(a => a.Name);
BsonDocument projected = await _dbContext.Things
.Find(x => x.Name == name)
.Project(projection)
.SingleOrDefaultAsync(token);
这可行,但自然会删减所有字典内容。我想更改投影的定义以包括该字段,但对构成元素进行过滤。假设我只想引入以 duck 开头的所述字典的键。尝试可能是这样的。
ProjectionDefinition<Thing> projection = Builders<Thing>
.Projection
.Include(a => a.Id)
.Include(a => a.Name)
.Include(a => a.Stuff.Where(b => b.Key.StartsWith("duck")));
导致异常如下。
System.NotSupportedException:不支持表达式树:{document}{configuration}
鉴于我对 MongoDb 的无知,我不知道是否应该添加一些东西、删除一些东西或完全忘记这个想法。我还尝试使用原始类型以能够以这种方式过滤内容,但我得到的唯一解决方案是后取,基本上是对检索到的数据进行处理。我想降低从数据库到我的服务的负载。
Thing projected = await _dbContext.Things
.Find(x => x.Name == name)
.Project<Thing>(projection)
.SingleOrDefaultAsync(token);
它是否可行,如果可行,如何(或至少谷歌搜索)?
努力证明:code examples、general operations、tutorials、wrong answers 等。它可能在某个地方,但我没能找到它(或者如果找到了就认出来)。
最后,我陷入了以下困境 - 上帝原谅我,因为我不知道自己在做什么。这是完全正确的方向还是一群疯狂的驴子会为此咬我的下背部?!
ProjectionDefinition<Thing, Thing> wtf = Builders<Thing>.Projection
.Expression(a => new Thing
{
Id = a.Id,
Name = a.Name,
Stuff = a.Stuff
.Where(b => b.Key == scope)
.ToDictionary(b => scope, b => b.Value)
});
【问题讨论】:
-
这似乎有点棘手,我没有太多想法,但
.NET的事情。但我为你找到了一些可能对你有帮助的东西 - mongodb.github.io/mongo-csharp-driver/2.7/reference/driver/… -
另请参阅有关您遇到的错误的问题 - stackoverflow.com/questions/55597781/…
-
请发布带有
stuff字段的示例文档以及您想要的项目内容。 -
@prasad_ 不确定您的要求。样本文件?描述它的类显示在顶部的第一个示例中。字段
Stuff是字符串作为键和字符串作为值的字典。我希望能够检索文档,但只提取字典部分的单个元素,而不是全部。如果我遗漏了什么,请详细说明。 -
一般来说,根据键名过滤字典(在 MongoDB 中是对象或嵌入文档)的问题是使用聚合查询来解决的。您可以将字典的键值对转换为数组(使用聚合运算符
$objectToArray)并通过键名过滤(在您的情况下可以使用正则表达式)数组。
标签: c# mongodb asp.net-core-3.1 projection .net-core-3.1