有一个看起来像这样的项目( 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
时我完全迷路了,我不确定这是否是最好的方法... 最佳答案
你快到了。请尝试以下步骤:
$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以避免重复使用过滤器值。 IE。
'description.lang':'ca','shortDescription.lang':'ca','variants.attrs.displayName.lang':'ca'