我在编写返回子文档数组中的元素的代码时遇到了困难。我实际上是在尝试将一个文档扁平化为一个强类型的新文档。我的文档看起来像;
{
"_id" : BinData(3, "7FRf4nbe60ev6XmGKBBW4Q=="),
"status" : NumberInt(1),
"title":"Central station",
"attributes" : [
{
"defId" : BinData(3, "QFDtR03NbkqwuhhG76wS8g=="),
"value" : "388",
"name" : null
},
{
"defId" : BinData(3, "RE3MT3clb0OdLEkkqhpFOg=="),
"value" : "",
"name" : null
},
{
"defId" : BinData(3, "pPgJR50h8kGdDaCcH2o17Q=="),
"value" : "Merkez",
"name" : null
}
]}
我想达到的是;
{
"title":"Central Station",
"value":"388"
}
我已经做了什么;
using (_dbContext)
{
var filter = Builders<CustomerModel>.Filter.Eq(q => q.Id, Guid.Parse("30B59585-CBFC-4CD5-A43E-0FDB0AE3167A")) &
Builders<CustomerModel>.Filter.ElemMatch(f => f.Attributes, q => q.DefId == Guid.Parse("47ED5040-CD4D-4A6E-B0BA-1846EFAC12F2"));
var projection = Builders<CustomerModel>.Projection.Include(f => f.Title).Include("attributes.value");
var document = _dbContext.Collection<CustomerModel>().Find(filter).Project(projection).FirstOrDefault();
if (document == null)
return null;
return BsonSerializer.Deserialize<TitleAndValueViewModel>(document);
}
注意:TitleAndCodeViewModel包含title和value属性。
这段代码返回;
{{ "_id" : CSUUID("30b59585-cbfc-4cd5-a43e-0fdb0ae3167a"), "title" : "388 güvenevler", "attributes" : [{ "value" : "388" }, { "value" : "" }, { "value" : "Merkez " }] }}
我正在尝试获取"value"; "388"但相反,我得到了另外两个值属性,即使为子文档添加了ElemMatch过滤器。
提前感谢您的帮助。
注意:我正在寻找c# mongodb驱动程序的答案。
选项1:(通过聚合)
db.collection.aggregate([
{
$match: {
_id: 5,
"attributes.defId": 1
}
},
{
"$addFields": {
"attributes": {
"$filter": {
"input": "$attributes",
"as": "a",
"cond": {
$eq: [
"$$a.defId",
1
]
}
}
}
}
},
{
$unwind: "$attributes"
},
{
$project: {
_id: 0,
title: 1,
value: "$attributes.value"
}
}
])
解释道:
- 匹配(适合为匹配字段添加索引)
- 只过滤需要的属性
- Unwind将数组转换为对象
- 项目只需要输出 游乐场
选项2:(find/$elemMatch)
db.collection.find({
_id: 5,
attributes: {
"$elemMatch": {
"defId": 1
}
}
},
{
_id: 0,
title: 1,
"attributes": {
"$elemMatch": {
"defId": 1
}
}
})
解释道:
- 通过_id和elemMatch属性匹配元素
- 规划必要的元素。(注意,这里还需要使用elemMatch来过滤精确匹配属性)(注意,这个版本不会识别是否有第二个属性具有相同的attribute. defid,如果发现属性的投影将是单个元素的数组,需要从应用端考虑)
操场2
通过指定
defId
db.collection.aggregate(
[{
$project: {
title: '$title',
attributes: {
$filter: {
input: '$attributes',
as: 'element',
cond: { $eq: ['$$element.defId', BinData(3, 'QFDtR03NbkqwuhhG76wS8g==')] }
}
}
}
}, {
$project: {
_id: 0,
title: '$title',
value: { $first: '$attributes.value' }
}
}])
结果:{
"title": "Central station",
"value": "388"
}