Mongodb 聚合获取数组中的具体对象
Mongodb aggregate get specifics objects in array
如何只获取 sales
数组中与 2021-10-14 日期匹配的对象?
如果至少有一个匹配,我目前汇总 return sales 数组的所有对象。
数据集文档
{
"name": "#0",
"sales": [{
"date": "2021-10-14",
"price": 3.69,
},{
"date": "2021-10-15",
"price": 2.79,
}]
},
{
"name": "#1",
"sales": [{
"date": "2021-10-14",
"price": 1.5,
}]
}
汇总
{
$match: {
sales: {
$elemMatch: {
date: '2021-10-14',
},
},
},
},
{
$group: {
_id: 0,
data: {
$push: '$sales',
},
},
},
{
$project: {
data: {
$reduce: {
input: '$data',
initialValue: [],
in: {
$setUnion: ['$$value', '$$this'],
},
},
},
},
}
结果
{"date": "2021-10-14","price": 3.69},
{"date": "2021-10-15","price": 2.79},
{"date": "2021-10-14","price": 1.5}
预期结果
{"date": "2021-10-14","price": 3.69},
{"date": "2021-10-14","price": 1.5}
您实际上需要使用 sales
数组中的 $replaceRoot
or $replaceWith
pipeline which takes in an expression that gives you the resulting document filtered using $arrayElemAt
(or $first
) and $filter
:
[
{ $match: { 'sales.date': '2021-10-14' } },
{ $replaceWith: {
$arrayElemAt: [
{
$filter: {
input: '$sales',
cond: { $eq: ['$$this.date', '2021-10-14'] }
}
},
0
]
} }
]
或
[
{ $match: { 'sales.date': '2021-10-14' } },
{ $replaceRoot: {
newRoot: {
$arrayElemAt: [
{
$filter: {
input: '$sales',
cond: { $eq: ['$$this.date', '2021-10-14'] }
}
},
0
]
}
} }
]
在$project
阶段,需要$filter
运算符,input
作为$reduce
运算符来过滤文档。
{
$project: {
data: {
$filter: {
input: {
$reduce: {
input: "$data",
initialValue: [],
in: {
$setUnion: [
"$$value",
"$$this"
],
}
}
},
cond: {
$eq: [
"$$this.date",
"2021-10-14"
]
}
}
}
}
}
使用 $unwind 怎么样:
.aggregate([
{$match: { sales: {$elemMatch: {date: '2021-10-14'} } }},
{$unwind: '$sales'},
{$match: {'sales.date': '2021-10-14'}},
{$project: {date: '$sales.date', price: '$sales.price', _id: 0}}
])
这会将销售分成不同的文档,每个文档只包含一个销售,并允许您轻松匹配条件。
参见:https://docs.mongodb.com/manual/reference/operator/aggregation/unwind/
如何只获取 sales
数组中与 2021-10-14 日期匹配的对象?
如果至少有一个匹配,我目前汇总 return sales 数组的所有对象。
数据集文档
{
"name": "#0",
"sales": [{
"date": "2021-10-14",
"price": 3.69,
},{
"date": "2021-10-15",
"price": 2.79,
}]
},
{
"name": "#1",
"sales": [{
"date": "2021-10-14",
"price": 1.5,
}]
}
汇总
{
$match: {
sales: {
$elemMatch: {
date: '2021-10-14',
},
},
},
},
{
$group: {
_id: 0,
data: {
$push: '$sales',
},
},
},
{
$project: {
data: {
$reduce: {
input: '$data',
initialValue: [],
in: {
$setUnion: ['$$value', '$$this'],
},
},
},
},
}
结果
{"date": "2021-10-14","price": 3.69},
{"date": "2021-10-15","price": 2.79},
{"date": "2021-10-14","price": 1.5}
预期结果
{"date": "2021-10-14","price": 3.69},
{"date": "2021-10-14","price": 1.5}
您实际上需要使用 sales
数组中的 $replaceRoot
or $replaceWith
pipeline which takes in an expression that gives you the resulting document filtered using $arrayElemAt
(or $first
) and $filter
:
[
{ $match: { 'sales.date': '2021-10-14' } },
{ $replaceWith: {
$arrayElemAt: [
{
$filter: {
input: '$sales',
cond: { $eq: ['$$this.date', '2021-10-14'] }
}
},
0
]
} }
]
或
[
{ $match: { 'sales.date': '2021-10-14' } },
{ $replaceRoot: {
newRoot: {
$arrayElemAt: [
{
$filter: {
input: '$sales',
cond: { $eq: ['$$this.date', '2021-10-14'] }
}
},
0
]
}
} }
]
在$project
阶段,需要$filter
运算符,input
作为$reduce
运算符来过滤文档。
{
$project: {
data: {
$filter: {
input: {
$reduce: {
input: "$data",
initialValue: [],
in: {
$setUnion: [
"$$value",
"$$this"
],
}
}
},
cond: {
$eq: [
"$$this.date",
"2021-10-14"
]
}
}
}
}
}
使用 $unwind 怎么样:
.aggregate([
{$match: { sales: {$elemMatch: {date: '2021-10-14'} } }},
{$unwind: '$sales'},
{$match: {'sales.date': '2021-10-14'}},
{$project: {date: '$sales.date', price: '$sales.price', _id: 0}}
])
这会将销售分成不同的文档,每个文档只包含一个销售,并允许您轻松匹配条件。
参见:https://docs.mongodb.com/manual/reference/operator/aggregation/unwind/