MongoDB 找到最后一个高点
MongoDB find the last high
我想获得比最新价格高的最近价格。示例 (MongoDB) 如下所示。
示例中的最晚日期是“2021/01/05”。
对于'id 0001',最近高于最新价格的价格是30,最新价格是20。
对于'id 0002',没有价格高于最新价格所以最接近的价格是最新价格(140)。
db.stock.find()
//结果
[
{'id':'0001','date':'2021/01/01','price':50}
{'id':'0001','date':'2021/01/02','price':40}
{'id':'0001','date':'2021/01/03','price':30}
{'id':'0001','date':'2021/01/04','price':10}
{'id':'0001','date':'2021/01/05','price':20}
{'id':'0002','date':'2021/01/01','price':100}
{'id':'0002','date':'2021/01/02','price':110}
{'id':'0002','date':'2021/01/03','price':120}
{'id':'0002','date':'2021/01/04','price':130}
{'id':'0002','date':'2021/01/05','price':140}
...
]
预期输出如下所示。
最接近的价格比10高20但小于30(最接近的价格比一个价格高),所以'days'在'0001'的情况下是1。
最接近的价格比130,120,110,100高140(最近的价格比四价高),所以'days'在'0002'的情况下是4。
[
{'id':'0001', 'latest_date':'2021/01/05',
'the_closest_date':'2021/01/03',
'the_closest_price':30,
'days':1},
{'id':'0002', 'latest_date':'2021/01/05',
'the_closest_date':'2021/01/05',
'the_closest_price':140,
'days':4}
]
我认为波纹管可以满足您的需求。
按日期排序,然后分组,然后找到价格第一个大的会员,如果找到就保存日期。
db.collection.aggregate([
{
"$sort": {
"date": -1
}
},
{
"$group": {
"_id": "$id",
"g": {
"$push": {
"price": "$price",
"date": "$date"
}
},
"latest-date": {
"$max": "$date"
},
"price": {
"$first": "$price"
}
}
},
{
"$addFields": {
"days-date-found": {
"$reduce": {
"input": "$g",
"initialValue": [
-1,
-1,
false
],
"in": {
"$let": {
"vars": {
"days_date_found": "$$value",
"m": "$$this"
},
"in": {
"$let": {
"vars": {
"days": {
"$arrayElemAt": [
"$$days_date_found",
0
]
},
"date": {
"$arrayElemAt": [
"$$days_date_found",
1
]
},
"found": {
"$arrayElemAt": [
"$$days_date_found",
2
]
}
},
"in": {
"$switch": {
"branches": [
{
"case": "$$found",
"then": "$$days_date_found"
},
{
"case": {
"$gt": [
"$$m.price",
"$price"
]
},
"then": [
"$$days",
"$$m.date",
true
]
}
],
"default": [
{
"$add": [
"$$days",
1
]
},
"$$m.date",
false
]
}
}
}
}
}
}
}
}
}
},
{
"$addFields": {
"days": {
"$arrayElemAt": [
"$days-date-found",
0
]
},
"closest-date": {
"$cond": [
{
"$arrayElemAt": [
"$days-date-found",
2
]
},
{
"$arrayElemAt": [
"$days-date-found",
1
]
},
"$latest-date"
]
}
}
},
{
"$unset": [
"days-date-found",
"g"
]
}
])
如果没有,您能否提供更多数据,以及查询后它们应该如何。
如我的表扬所述,您的要求不一致。你也没有解释如何确定字段 days
.
这是我的解决方案:
db.collection.aggregate([
{ $sort: { date: 1 } },
{
$group: {
_id: "$id",
data: { $push: "$$ROOT" },
latest_price: { $last: "$price" },
latest_date: { $last: "$date" }
}
},
{ // Remove this stage if the latest price/date can be the result. However, then it will be **always** the latest one
$set: {
data: {
$slice: [ "$data", 0, { $subtract: [ { $size: "$data" }, 1 ] } ]
}
}
},
{ // Filter days where price > latest price
$set: {
data: {
$filter: {
input: "$data",
cond: { $gt: [ "$$this.price", "$latest_price" ] }
}
}
}
},
{ // Calculate difference between price and latest price
$set: {
data: {
$map: {
input: "$data",
in: {
$mergeObjects: [
"$$this",
{
diff: {
$subtract: [
"$$this.price",
"$latest_price"
]
}
}
]
}
}
}
}
},
{ // Filter by minimum difference (note, there might be more than just one)
$set: {
data: {
$filter: {
input: "$data",
cond: { $eq: [ "$$this.diff", { $min: "$data.diff" } ] }
}
}
}
},
{ // Compose final output
$project: {
latest_date: 1,
the_closest_date: { $first: "$data.date" },
the_closest_price: { $first: "$data.price" }
}
}
])
我想获得比最新价格高的最近价格。示例 (MongoDB) 如下所示。
示例中的最晚日期是“2021/01/05”。
对于'id 0001',最近高于最新价格的价格是30,最新价格是20。 对于'id 0002',没有价格高于最新价格所以最接近的价格是最新价格(140)。
db.stock.find()
//结果
[
{'id':'0001','date':'2021/01/01','price':50}
{'id':'0001','date':'2021/01/02','price':40}
{'id':'0001','date':'2021/01/03','price':30}
{'id':'0001','date':'2021/01/04','price':10}
{'id':'0001','date':'2021/01/05','price':20}
{'id':'0002','date':'2021/01/01','price':100}
{'id':'0002','date':'2021/01/02','price':110}
{'id':'0002','date':'2021/01/03','price':120}
{'id':'0002','date':'2021/01/04','price':130}
{'id':'0002','date':'2021/01/05','price':140}
...
]
预期输出如下所示。
最接近的价格比10高20但小于30(最接近的价格比一个价格高),所以'days'在'0001'的情况下是1。
最接近的价格比130,120,110,100高140(最近的价格比四价高),所以'days'在'0002'的情况下是4。
[
{'id':'0001', 'latest_date':'2021/01/05',
'the_closest_date':'2021/01/03',
'the_closest_price':30,
'days':1},
{'id':'0002', 'latest_date':'2021/01/05',
'the_closest_date':'2021/01/05',
'the_closest_price':140,
'days':4}
]
我认为波纹管可以满足您的需求。 按日期排序,然后分组,然后找到价格第一个大的会员,如果找到就保存日期。
db.collection.aggregate([
{
"$sort": {
"date": -1
}
},
{
"$group": {
"_id": "$id",
"g": {
"$push": {
"price": "$price",
"date": "$date"
}
},
"latest-date": {
"$max": "$date"
},
"price": {
"$first": "$price"
}
}
},
{
"$addFields": {
"days-date-found": {
"$reduce": {
"input": "$g",
"initialValue": [
-1,
-1,
false
],
"in": {
"$let": {
"vars": {
"days_date_found": "$$value",
"m": "$$this"
},
"in": {
"$let": {
"vars": {
"days": {
"$arrayElemAt": [
"$$days_date_found",
0
]
},
"date": {
"$arrayElemAt": [
"$$days_date_found",
1
]
},
"found": {
"$arrayElemAt": [
"$$days_date_found",
2
]
}
},
"in": {
"$switch": {
"branches": [
{
"case": "$$found",
"then": "$$days_date_found"
},
{
"case": {
"$gt": [
"$$m.price",
"$price"
]
},
"then": [
"$$days",
"$$m.date",
true
]
}
],
"default": [
{
"$add": [
"$$days",
1
]
},
"$$m.date",
false
]
}
}
}
}
}
}
}
}
}
},
{
"$addFields": {
"days": {
"$arrayElemAt": [
"$days-date-found",
0
]
},
"closest-date": {
"$cond": [
{
"$arrayElemAt": [
"$days-date-found",
2
]
},
{
"$arrayElemAt": [
"$days-date-found",
1
]
},
"$latest-date"
]
}
}
},
{
"$unset": [
"days-date-found",
"g"
]
}
])
如果没有,您能否提供更多数据,以及查询后它们应该如何。
如我的表扬所述,您的要求不一致。你也没有解释如何确定字段 days
.
这是我的解决方案:
db.collection.aggregate([
{ $sort: { date: 1 } },
{
$group: {
_id: "$id",
data: { $push: "$$ROOT" },
latest_price: { $last: "$price" },
latest_date: { $last: "$date" }
}
},
{ // Remove this stage if the latest price/date can be the result. However, then it will be **always** the latest one
$set: {
data: {
$slice: [ "$data", 0, { $subtract: [ { $size: "$data" }, 1 ] } ]
}
}
},
{ // Filter days where price > latest price
$set: {
data: {
$filter: {
input: "$data",
cond: { $gt: [ "$$this.price", "$latest_price" ] }
}
}
}
},
{ // Calculate difference between price and latest price
$set: {
data: {
$map: {
input: "$data",
in: {
$mergeObjects: [
"$$this",
{
diff: {
$subtract: [
"$$this.price",
"$latest_price"
]
}
}
]
}
}
}
}
},
{ // Filter by minimum difference (note, there might be more than just one)
$set: {
data: {
$filter: {
input: "$data",
cond: { $eq: [ "$$this.diff", { $min: "$data.diff" } ] }
}
}
}
},
{ // Compose final output
$project: {
latest_date: 1,
the_closest_date: { $first: "$data.date" },
the_closest_price: { $first: "$data.price" }
}
}
])