Sub*_*sta 4 c# mongodb mongodb-.net-driver asp.net-core
我有一个结构看起来像这样的文档,带有嵌套的子文档
{
"_id":ObjectId("50419077c2e6a1e18a489a0f"),
"user":"Jone Doe",
"fooArray":[
{
"plot":"circle",
"color":"yellow",
},
{
"plot":"circle",
"color":"red",
},
{
"plot":"square",
"color":"green",
}
]
}
Run Code Online (Sandbox Code Playgroud)
我想在这个具有圆形图的文档中检索 fooArray 中的所有匹配元素。
这是我试过的
var filter = FilterBuilder.filter.Eq(doc => doc.User, User);
var projection = ProjectionBuilder
.Exclude(doc => doc.Id)
.Exclude(doc => doc.User)
.Include(doc => doc.FooArray)
.ElemMatch(x => x.FooArray, y => y.Plot == "circle");
var definition = new OperationDefinitions<ShapeDocument> { Filter = filter };
return await Performer.Perform(definition, async (def, collection) =>
{
var findResult = collection.Find(def.Filter).Project(projection);
var result = await findResult.SingleOrDefaultAsync();
});
Run Code Online (Sandbox Code Playgroud)
这就是我得到的
{
"fooArray":[
{
"plot":"circle",
"color":"yellow",
}
]
}
Run Code Online (Sandbox Code Playgroud)
但它只给了我第一个匹配元素,而不是所有绘图等于圆的元素
{
"fooArray":[
{
"plot":"circle",
"color":"yellow",
},
{
"plot":"circle",
"color":"red",
}
]
}
Run Code Online (Sandbox Code Playgroud)
我确实阅读了提到的 mongodb 文档
" $elemMatch 运算符将查询结果中的字段内容限制为仅包含与 $elemMatch 条件匹配的第一个元素。"
不太确定如何实现这一目标!
这个问题并没有完全描述用例,所以我根据一些假设提出了一些潜在的选项供您探索,特别是它们依赖于 LINQ 可用并且一次定位一个文档(并且您可能不想要比实际需要更多的代码):
1)你所拥有的变化。使用find带有投影和 LINQ 表达式的标准。
var projection = Builders<ShapeDocument>.Projection
.Expression(x => x.fooArray.Where(y => y.plot == "circle"));
var items1 = collection
.Find(x => x.user == "Jone Doe")
.Project(projection)
.ToList();
Run Code Online (Sandbox Code Playgroud)
2)使用聚合管道(您可以使用与上面相同的投影)
var pipeline = collection
.Aggregate()
.Match(x => x.user == "Jone Doe")
.Project(i => new
{
x = i.fooArray.Where(x => x.plot == "circle")
});
var items2 = pipeline.SingleOrDefault();
Run Code Online (Sandbox Code Playgroud)
3) 使用所有数组元素将文档拉回,然后使用 LINQ 进行本地过滤。从好的方面来说,这是少量可读代码,但是,它确实在过滤之前将整个文档带回来。根据您的确切用途,这可能是可以接受的。
var items3 = collection.AsQueryable()
.SingleOrDefault(x => x.user == "Jone Doe")
.fooArray.Where(x => x.plot == "circle");
Run Code Online (Sandbox Code Playgroud)
如果LINQ真的不是一个选项,然后有一个例子在这里,告诉您如何可能会在投影转换成不是我们LINQ。完全未经测试,但大致如下:
var filter = new BsonDocument {
{"input", "$items"},
{"as", "item" },
{"cond", new BsonDocument {
// Fill in the condition values
{ "", new BsonArray { "", xxx } } }
}
};
var project = new BsonDocument {
{ "items", new BsonDocument { { "$filter", filter} } }
};
var pipeline = collection.Aggregate().Project(project);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5375 次 |
| 最近记录: |