问题
I am coding an app in which there are some weather sensors that send air's temperature and humidity to the server every 5 minutes.
I would like to draw a chart of how the temperature and humidity change i.e overnight. My idea is to draw the chart basing on data from last 24 hours.
I cannot figure it out by myself, so I thought maybe I could seek help here. Of course, each measurement document has a field called createdAt
which has the timestamp of the moment it has been created.
I need to build a mongoose query that will retrieve measurements collected in the last 24 hours, but only take one measurement from each hour. With the 5min time interval with the device's measurements I will have 12 documents created every hour. I would like to retrieve only one of them per each hour.
So far I was able to come up with this (used gt
to get the last 24 hours measurements, dont know how to get only one document per each hour):
Measurements.find({ "createdAt": { $gt: new Date(Date.now() - 24*60*60 * 1000) } })
回答1:
Use aggregation
this is a great article for how to group your documents then pick one item per document.
You also need to filter docs for last 24 hours, then project for find and hour
from timestamp.
If you need, lets say, last 48 hours, you need to group by hour and day.
Your query will something like this
collection.aggregate([
{
"$filter": {
"createdAt": { $gt: new Date(Date.now() - 24*60*60 * 1000) }
}
},
{
"$project": {
"h": {"$hour" : "$createdAt"},
"original_doc": "$$ROOT"
}
},
{
"$group": {
"_id": { "hour": "$h" },
"docs": { $push: "$original_doc" }
}
},
{
$replaceRoot: {
newRoot: { $arrayElemAt: ["$docs", 0] }
}
}
])
回答2:
You can use below aggregation to get first and last document from each hour.
$sort
to order documents by createdAt followed by $group
on hour to output first and last document for each hour.
$$ROOT
is system variable to access the whole document.
Measurements.aggregate([
{"$match" : {"createdAt":{"$gt":new Date(Date.now() - 24*60*60 * 1000)}}},
{"$sort":{"createdAt":-1}},
{"$group":{
"_id":{"$hour":"$createdAt"},
"first":{"$first":"$$ROOT"},
"last":{"$last":"$$ROOT"}
}}
])
回答3:
It Works for me:
var pipeline = [
{
$match: {
$and: [
{createdAt: {$gte: startDate}},
{createdAt: {$lte: endDate}},
{eventType: 'update'}
]
}
},
{$sort: {createdAt: -1}},
{
$group: {
_id: "$person",
persons: {$push: "$$ROOT"}
}
},
{
$replaceRoot: {
newRoot: {$arrayElemAt: ["$persons", 0]}
}
},
{
$lookup: {
from: 'people',
localField: 'person',
foreignField: '_id',
as: 'person'
}
},
{$unwind: "$person"}
];
VisitEvent.aggregate(pipeline)
.then(function (events) {ere
来源:https://stackoverflow.com/questions/48244163/mongoose-query-for-documents-from-last-24-hours-only-one-document-per-hour