有一个项目(mongoose)架构看起来像这样(简化为问题的重要性):
{
brand: {
name: String,
},
title: String,
description: [{ lang: String, text: String }],
shortDescription: [{ lang: String, text: String }],
variants: {
cnt: Number,
attrs: [
{
displayType: String,
displayContent: String,
displayName: [{ lang: String, text: String }],
name: String,
},
],
}
}
我正在尝试按语言过滤项目,因此我构建了以下查询:
db.items.aggregate([
{ $match: { 'description.lang': 'ca', 'shortDescription.lang': 'ca' } },
{ $project: {
'brand.name': 1,
title: 1,
description: {
'$filter': {
input: '$description',
as: 'description',
cond: { $eq: ['$$description.lang', 'ca'] }
}
},
shortDescription: {
'$filter': {
input: '$shortDescription',
as: 'shortDescription',
cond: { $eq: ['$$shortDescription.lang', 'ca'] }
}
},
'variants.cnt': 1,
'variants.attrs': 1
} }
])
它按预期工作:按语言过滤description
和shortDescription
。现在我想知道是否有可能过滤每个variants.attrs.$.displayName
。有没有办法做到这一点?
我一直在尝试$unwind
variant.attrs
但是当我再次尝试$group
时我完全迷失了,我不确定这是否是最好的方式... < / p>
答案 0 :(得分:8)
你快到了。请尝试以下步骤:
$unwind
阶段之前使用$project
阶段展开外部文档数组,即variants.attrs
variants.attrs.displayName
阶段为子数组$project
添加过滤器。variants
密钥的所有子字段。 $group
阶段和分组。使用$push
逐级重建子数组。最后,添加$project
阶段以将文档重建为其原始结构。
db.items.aggregate([
{ $match: { 'description.lang': 'ca', 'shortDescription.lang': 'ca' } },
{ $unwind : "$variants.attrs" },
{ $project: {
'_id' : 1,
'brand.name': 1,
title: 1,
description: {
'$filter': {
input: '$description',
as: 'description',
cond: { $eq: ['$$description.lang', 'ca'] }
}
},
shortDescription: {
'$filter': {
input: '$shortDescription',
as: 'shortDescription',
cond: { $eq: ['$$shortDescription.lang', 'ca'] }
}
},
'variants.attrs.displayName' : {
'$filter' : {
input: '$variants.attrs.displayName',
as: 'variants_attrs_displayName',
cond: { $eq : ['$$variants_attrs_displayName.lang','ca']}
}
},
'variants.cnt': 1,
'variants.attrs.displayType': 1,
'variants.attrs.displayContent' : 1,
'variants.attrs.name' : 1
}
} , { $group:
{
_id : {
_id: "$_id",
title: "$title",
brand:"$brand",
description:"$description",
shortDescription:"$shortDescription",
variants_cnt : "$variants.cnt"
},
variants_attrs : { $push :
{
displayType : "$variants.attrs.displayType",
displayContent : "$variants.attrs.displayContent",
displayName : "$variants.attrs.displayName",
name: "$variants.attrs.name"
}
}
}
},
{ $project :
{
"_id" : 0,
brand : "$_id.brand",
title : "$_id.title",
description : "$_id.description",
shortDescription : "$_id.shortDescription",
variants : {
cnt : "$_id.variants_cnt" ,
attrs : "$variants_attrs"
}
}
}
])
根据您的使用情况,您应重新考虑data model design以避免重复使用过滤器值。即 &#39; description.lang&#39;:&#39; ca&#39;,&#39; shortDescription.lang&#39;:&#39; ca&#39;,&#39; variants.attrs.displayName。 lang&#39;:&#39; ca&#39;