我有一个具有以下结构的文档集合:
{'_id': 'xxx',
'name': 'some_name',
'data': {
'first_thing': [1, 2, 3, 4],
'second_thing': [5, 3, 2, 4],
}
}
我的目标是计算“数据”下每个子字段的值的平均值和标准差。我尝试以下查询单个子字段:
cursor = db.testcoll.aggregate([
{
'$project': {
'_id': '$name',
'data.first_thing.mean': {'$avg': '$data.first_thing'},
'data.first_thing.std': {'$stdDevPop': '$data.first_thing'}
}
}
])
结果是,字段“数据”是一个列表,其中对原始列表“ first_thing”中的每个元素重复进行聚合$avg
和$stdDevPop
:
{'data': {
'first_thing': [
{'mean': 2.5, 'std': 1.118033988749895},
{'mean': 2.5, 'std': 1.118033988749895},
{'mean': 2.5, 'std': 1.118033988749895},
{'mean': 2.5, 'std': 1.118033988749895}]},
'_id': 'some_name'
}
很明显,我只需要一次聚合,即:
{'data': {
'first_thing': {
'mean': 2.5,
'std': 1.118033988749895
},
'_id': 'some_name'
}
我观察到,当我将结果字段的名称更改为除原始字段名称之外的其他名称时,聚合仅执行一次。因此,查询:
cursor = db.testcoll.aggregate([
{
'$project': {
'_id': '$name',
'data.some_thing.mean': {'$avg': '$data.first_thing'},
'data.some_thing.std': {'$stdDevPop': '$data.first_thing'}
}
}
])
给我我想要的。但是,在生成的文档中,“ first_thing”的集合位于称为“ some_thing”的子字段中。
如何更改查询以使结果为:
{'data': {
'first_thing': {
'mean': 2.5,
'std': 1.118033988749895},
'_id': 'some_name'
}
?
我进一步观察到删除了“数据”。就像在结果字段的命名中一样
cursor = db.testcoll.aggregate([
{
...
'first_thing.mean': {'$avg': '$data.first_thing'},
...
}}])
结果符合预期;唯一的缺点是所有“事物”都位于结果文档的顶层。但是,我需要它们位于子字段中。
答案 0 :(得分:0)
data.first_thing
是一个数组,因此您需要为此数组中的每个项目设置值。
尝试一下:
db.collection.aggregate([
{
"$set": {
"data.mean": { "$avg": "$data.first_thing" },
"data.std": { "$stdDevPop": "$data.first_thing" }
}
},
{ "$set": { "data.first_thing": null } },
{
"$project": {
"data.first_thing.mean": "$data.mean",
"data.first_thing.std": "$data.std",
"_id": "$name",
}
}
])
或这个:
db.collection.aggregate([
{
"$set": {
"data.first_thing.mean": { "$avg": "$data.first_thing" },
"data.first_thing.std": { "$stdDevPop": "$data.first_thing" }
}
},
{
"$project": {
"data.first_thing": { $setUnion: "$data.first_thing" },
"_id": "$name"
}
}
])
在我看来,之后再使用$unwind
和$group
似乎是过大的选择。
答案 1 :(得分:0)
之所以发生,是因为first_thing
是一个数组。您可以通过多种方式实现目标。
unwind
展平数组并将其分组的方法。代码在下面给出
[
{
"$project": {
"_id": "$name",
"data.first_thing.mean": {
"$avg": "$data.first_thing"
},
"data.first_thing.std": {
"$stdDevPop": "$data.first_thing"
}
}
},
{
"$unwind": "$data.first_thing"
},
{
$group: {
_id: "$_id",
data: {
$addToSet: {
first_thing: [
"$data.first_thing"
]
}
}
}
}
]
代码在下面给出
[
{
"$project": {
"_id": "$name",
"mean": {
"$avg": "$data.first_thing"
},
"std": {
"$stdDevPop": "$data.first_thing"
}
}
},
{
$addFields: {
"data.first_thing": [
{
mean: "$mean",
std: "$std"
}
]
}
}
]