gpt4 book ai didi

php - 数组元素聚合中的mongodb avg

转载 作者:可可西里 更新时间:2023-11-01 10:43:07 25 4
gpt4 key购买 nike

我有以下集合结构

{
"_id": {
"d_timestamp": NumberLong(1429949699),
"d_isostamp": ISODate("2015-04-25T08:14:59.0Z")
},
"XBT-USD-cpx-okc": [
{
"buySpread": -1.80081
}

我运行以下聚合

$spreadName ='XBT-USD-stp-nex';
$pipe = array(
array(
'$match' => array(
'_id.d_isostamp' => array(
'$gt' => $start, '$lt' => $end
)
)
),
array(
'$project' => array(
'sellSpread' =>'$'.$spreadName.'.sellSpread',
)
),
array(
'$group' => array(
'_id' => array(
'isodate' => array(
'$minute' => '$_id.d_isostamp'
)
),
'rsell_spread' => array(
'$avg' => '$sellSpread'
),
)
),
);

$out = $collection->aggregate($pipe ,$options);

我得到的结果是 rsell_spread 的值 0,而如果我运行 $max 而不是 $avg $group ,我得到了 rsell_spread 的准确值,具有以下结构

{
"_id": {
"isodate": ISODate("2015-04-25T08:00:58.0Z")
},
"rsell_spread": [
-4.49996▼
]
}

所以我有两个问题:

1/为什么$avg函数不起作用?

2/例如,当我使用 $max(只是一个常规数字)时,我如何才能得到不在数组中的结果?

最佳答案

  1. $avg组累加器运算符确实有效,只是在您的情况下它被应用于数组中的元素并因此给出“不正确”的结果。

  2. 当您使用 $max组累加器运算符,它返回将表达式应用于一组文档中的每个文档所产生的最大值,因此在您的示例中它返回了最大数组。

为了证明这一点,考虑将一些示例文档添加到 mongoshell 中的测试集合中:

db.test.insert([
{
"_id" : {
"d_timestamp" : NumberLong(1429949699),
"d_isostamp" : ISODate("2015-04-25T08:14:59.000Z")
},
"XBT-USD-stp-nex" : [
{
"sellSpread" : -1.80081
}
]
},
{
"_id" : {
"d_timestamp" : NumberLong(1429949710),
"d_isostamp" : ISODate("2015-04-25T08:15:10.000Z")
},
"XBT-USD-stp-nex" : [
{
"sellSpread" : -1.80079
}
]
},
{
"_id" : {
"d_timestamp" : NumberLong(1429949720),
"d_isostamp" : ISODate("2015-04-25T08:15:20.000Z")
},
"XBT-USD-stp-nex" : [
{
"sellSpread" : -1.80083
}
]
},
{
"_id" : {
"d_timestamp" : NumberLong(1429949730),
"d_isostamp" : ISODate("2015-04-25T08:15:30.000Z")
},
"XBT-USD-stp-nex" : [
{
"sellSpread" : -1.80087
}
]
}
])

现在,在 mongoshell 中复制上面的相同操作:

var spreadName = "XBT-USD-stp-nex",
start = new Date(2015, 3, 25),
end = new Date(2015, 3, 26);
db.test.aggregate([
{
"$match": {
"_id.d_isostamp": { "$gte": start, "$lte": end }
}
},
{
"$project": {
"sellSpread": "$"+spreadName+".sellSpread"
}
}/*,<--- deliberately omitted the $unwind stage from the pipeline to replicate the current pipeline
{
"$unwind": "$sellSpread"
}*/,
{
"$group": {
"_id": {
"isodate": { "$minute": "$_id.d_isostamp"}
},
"rsell_spread": {
"$avg": "$sellSpread"
}
}
}
])

输出:

/* 0 */
{
"result" : [
{
"_id" : {
"isodate" : 15
},
"rsell_spread" : 0
},
{
"_id" : {
"isodate" : 14
},
"rsell_spread" : 0
}
],
"ok" : 1
}

解决方案是包含一个 $unwind $project 之后的运算符管道阶段步骤,这将从输入文档中解构 XBT-USD-stp-nex 数组字段,并为每个元素输出一个文档。每个输出文档用一个元素值替换数组。这将使 $avg 成为可能组累加器运算符工作。

包括这将给出聚合结果:

/* 0 */
{
"result" : [
{
"_id" : {
"isodate" : 15
},
"rsell_spread" : -1.80083
},
{
"_id" : {
"isodate" : 14
},
"rsell_spread" : -1.80081
}
],
"ok" : 1
}

因此您在 PHP 中的最终工作聚合应该是:

$spreadName ='XBT-USD-stp-nex';
$pipe = array(
array(
'$match' => array(
'_id.d_isostamp' => array(
'$gt' => $start, '$lt' => $end
)
)
),
array(
'$project' => array(
'sellSpread' =>'$'.$spreadName.'.sellSpread',
)
),
array('$unwind' => '$sellSpread'),
array(
'$group' => array(
'_id' => array(
'isodate' => array(
'$minute' => '$_id.d_isostamp'
)
),
'rsell_spread' => array(
'$avg' => '$sellSpread'
),
)
),
);

$out = $collection->aggregate($pipe ,$options);

关于php - 数组元素聚合中的mongodb avg,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30077402/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com