子文档数组中的项目单个字段返回多个



我在编写返回子文档数组中的元素的代码时遇到了困难。我实际上是在尝试将一个文档扁平化为一个强类型的新文档。我的文档看起来像;

{ 
"_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"
}
}
])

解释道:

  1. 匹配(适合为匹配字段添加索引)
  2. 只过滤需要的属性
  3. Unwind将数组转换为对象
  4. 项目只需要输出
  5. 游乐场

选项2:(find/$elemMatch)

db.collection.find({
_id: 5,
attributes: {
"$elemMatch": {
"defId": 1
}
}
},
{
_id: 0,
title: 1,
"attributes": {
"$elemMatch": {
"defId": 1
}
}
})

解释道:

  1. 通过_id和elemMatch属性匹配元素
  2. 规划必要的元素。(注意,这里还需要使用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"
}