MongoDB (Mongoose) - 在唯一字段下分组数据
MongoDB (Mongoose) - grouping data under a unique field
在 collection 中,我有这样的条目:
[
{
_id: new ObjectId('61cae11f8fc0b2e3b045be04'),
location: 'Station One',
datetime: ISODate('2019-02-02T12:54:57.937Z'),
sensorType: 'temperature',
value: -1.8,
__v: 0,
},
{
_id: new ObjectId('61cae11f8fc0b2e3b045be05'),
location: 'Station two',
datetime: ISODate('2019-02-02T09:49:39.200Z'),
sensorType: 'temperature',
value: -2,
__v: 0,
},
];
我有一个聚合查询来获取每个传感器类型的 min/max 值,就像这样
const queryMinMax = FarmDataModel.aggregate([
{
$match: match,
},
{
$sort: {
value: 1,
},
},
{
$group: {
_id: {
sensorType: '$sensorType', location: '$location',
},
min: {
$first: '$$ROOT',
},
max: {
$last: '$$ROOT',
},
},
},
{
$sort: {
'_id.location': 1,
'_id.sensorType': 1,
},
},
{
$project: {
_id: 1,
max: {
value: '$max.value',
month: { $month: '$max.datetime' },
year: { $year: '$max.datetime' },
day: { $dayOfMonth: '$max.datetime' },
},
min: {
value: '$min.value',
month: { $month: '$min.datetime' },
year: { $year: '$min.datetime' },
day: { $dayOfMonth: '$min.datetime' },
},
},
},
]);
这让我为每种传感器类型和相应的最小最大值获取一行。
我想做的是将每个传感器类型分组在一个位置下,这样查询就会 return 像这样:
{
'Station One': {
temperature: {
min: { value: number; date: date }
max: { value: number; date: date },
},
pH: {
min: { value: number; date: date }
max: { value: number; date: date },
},
},
'Station Two': {
temperature: {
min: { value: number; date: date }
max: { value: number; date: date },
},
pH: {
min: { value: number; date: date }
max: { value: number; date: date },
},
},
};
所以如果之前我会得到 4 行,每个位置的每个传感器类型一排,现在我会得到两行,每个位置一排,在那些下面有 key:value 对每个传感器类型
我可以修改我的查询来实现吗?
您可以只在现有管道的基础上构建,只需要另一个 $group
阶段按站点对数据进行分组,然后对其进行一些重组以匹配您想要的输出,如下所示:
db.collection.aggregate([
... existing pipeline,
{
$group: {
_id: "$_id.location",
sensorData: {
$push: {
k: "$_id.sensorType",
v: {
max: "$max",
min: "$min"
}
}
}
}
},
{
"$replaceRoot": {
"newRoot": {
"$arrayToObject": [
[
{
k: "$_id",
v: {
"$arrayToObject": "$sensorData"
}
}
]
]
}
}
}
])
在 collection 中,我有这样的条目:
[
{
_id: new ObjectId('61cae11f8fc0b2e3b045be04'),
location: 'Station One',
datetime: ISODate('2019-02-02T12:54:57.937Z'),
sensorType: 'temperature',
value: -1.8,
__v: 0,
},
{
_id: new ObjectId('61cae11f8fc0b2e3b045be05'),
location: 'Station two',
datetime: ISODate('2019-02-02T09:49:39.200Z'),
sensorType: 'temperature',
value: -2,
__v: 0,
},
];
我有一个聚合查询来获取每个传感器类型的 min/max 值,就像这样
const queryMinMax = FarmDataModel.aggregate([
{
$match: match,
},
{
$sort: {
value: 1,
},
},
{
$group: {
_id: {
sensorType: '$sensorType', location: '$location',
},
min: {
$first: '$$ROOT',
},
max: {
$last: '$$ROOT',
},
},
},
{
$sort: {
'_id.location': 1,
'_id.sensorType': 1,
},
},
{
$project: {
_id: 1,
max: {
value: '$max.value',
month: { $month: '$max.datetime' },
year: { $year: '$max.datetime' },
day: { $dayOfMonth: '$max.datetime' },
},
min: {
value: '$min.value',
month: { $month: '$min.datetime' },
year: { $year: '$min.datetime' },
day: { $dayOfMonth: '$min.datetime' },
},
},
},
]);
这让我为每种传感器类型和相应的最小最大值获取一行。 我想做的是将每个传感器类型分组在一个位置下,这样查询就会 return 像这样:
{
'Station One': {
temperature: {
min: { value: number; date: date }
max: { value: number; date: date },
},
pH: {
min: { value: number; date: date }
max: { value: number; date: date },
},
},
'Station Two': {
temperature: {
min: { value: number; date: date }
max: { value: number; date: date },
},
pH: {
min: { value: number; date: date }
max: { value: number; date: date },
},
},
};
所以如果之前我会得到 4 行,每个位置的每个传感器类型一排,现在我会得到两行,每个位置一排,在那些下面有 key:value 对每个传感器类型
我可以修改我的查询来实现吗?
您可以只在现有管道的基础上构建,只需要另一个 $group
阶段按站点对数据进行分组,然后对其进行一些重组以匹配您想要的输出,如下所示:
db.collection.aggregate([
... existing pipeline,
{
$group: {
_id: "$_id.location",
sensorData: {
$push: {
k: "$_id.sensorType",
v: {
max: "$max",
min: "$min"
}
}
}
}
},
{
"$replaceRoot": {
"newRoot": {
"$arrayToObject": [
[
{
k: "$_id",
v: {
"$arrayToObject": "$sensorData"
}
}
]
]
}
}
}
])