MongoDb get last and max values with timestamps - mongodb

I am new to MongoDb as I only installed it yesterday...
I have a collection of temperature readings from n rooms:
[
{
"key": "livingRoom",
"name": "Living Room",
"temp": 19.437,
"ts": "2017-04-29T07:20:22.000Z"
},
{
"key": "bedroom",
"name": "Bedroom",
"temp": 24.875,
"ts": "2017-04-29T07:21:14.000Z"
}
]
and I want to get the current (last) temperature and the min/max over the last 24 hours for each room. I also want the timestamp of the min and max values.
I am 90% of the way there but as always that last 10% seems to take 90% of the time.
I have this aggregation:
{
"$group": {
"_id": "$key",
"temp": {"$last": "$temp"},
"name": {"$last": "$name"},
"ts": {"$last": "$ts"},
"maxTemp": {"$max": "$temp"},
"minTemp": {"$min": "$temp"}
}
}
That produces this result:
[
{
"_id": "bedroom",
"temp": 22.25,
"name": "Bedroom",
"ts": "2017-04-30T07:31:30.000Z",
"maxTemp": 24.875,
"minTemp": 21.437
},
{
"_id": "livingRoom",
"temp": 18.75,
"name": "Living Room",
"ts": "2017-04-30T07:39:38.000Z",
"maxTemp": 19.625,
"minTemp": 17.625
}
]
but of course that doesn't include the timestamp of the min and max values.
This question:
Multiple group operations using Mongo aggregation framework was useful and seems to indicate that I can't do what I want to.
I was planning on using different groups with different sorts to get the different aggregations that I want but as a group acts on the result of the last group it seems that what I am trying to do can't be done by mongo.

Related

Vega-Lite - How to calculate the difference of values from different rows in my data?

My current minimal example looks like:
{
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
"data": {"values": [
{"year":2022, "week":1, "val":5},
{"year":2022, "week":2, "val":4},
{"year":2022, "week":3, "val":6},
{"year":2021, "week":1, "val":3},
{"year":2021, "week":2, "val":7}
]},
"mark":"line",
"encoding": {
"x":{"field":"week"},
"y":{"field":"val"},
"color":{"field":"year"}
}
}
I would like to calculate the difference of the week's values for this year and the previous year (if one of the values is missing, the difference should not be displayed). So for week 1 I would like to get a difference of 2 (=5 - 3) and for week 2 I would like to get a difference of -3 (= 4 - 7).
It seems like a common thing to do, but I found no examples or documentation solving this problem. I managed to produce the desired output with a kind of very ugly LAG transform but this does only work, if there are the same number of weeks in both years which is not always the case.
Maybe, one could somehow transform the data, that the week's values of this and the previous year appear in the same column?
This works for me.
{
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
"data": {
"name": "myData",
"values": [
{"year": 2022, "week": 1, "val": 5},
{"year": 2022, "week": 2, "val": 4},
{"year": 2022, "week": 3, "val": 6},
{"year": 2021, "week": 1, "val": 3},
{"year": 2021, "week": 2, "val": 7}
]
},
"transform": [
{
"window": [{"op": "lead", "field": "val", "as": "lastVal"}],
"groupby": ["week"]
},
{
"calculate": "datum.lastVal==null?0: datum.val - datum.lastVal",
"as": "diff"
}
],
"mark": "line",
"encoding": {
"x": {"field": "week"},
"y": {"field": "val"},
"color": {"field": "year"}
}
}

How can I compute the income of the sellerId of the products?

I'm trying to learn the advanced mongodb+mongoose function, so this is the result of my orders, and what I'm trying to do here is to compute the total amounts related to the sellerId
So in this one, I have two documents, the document 1 have an amount of 99 and and the other one is 11
so I need to get the sum of two. I've been searching and found the aggregate, but I can't figure out how I can combine the two documents.
[
{
"_id": "6360d1d0bd860240e2589564",
"userId": "6360cf687e186ebe29ab2a29",
"products": [
{
"productId": "6360cdd166480badb8c1e05b",
"quantity": 1,
"sellerId": "6360c6ed05e1e99034b5f7eb",
"_id": "6360d1d0bd860240e2589565"
}
],
"amount": 99,
"location": "asdsad",
"time": "asdsad",
"status": "pending",
"tax": 0.99,
},
{
"_id": "6360d7978044f3048e59bf34",
"userId": "6360d50dbd860240e258c585",
"products": [
{
"productId": "6360d7528044f3048e59bb6c",
"quantity": 1,
"sellerId": "6360d4d5bd860240e258c582",
"_id": "6360d7978044f3048e59bf35"
},
{
"productId": "6360d7868044f3048e59bd8c",
"quantity": 1,
"sellerId": "6360d4d5bd860240e258c582",
"_id": "6360d7978044f3048e59bf36"
}
],
"amount": 11,
"location": "Gym",
"time": "8:00 AM",
"status": "pending",
"tax": 0.11,
}
]
This might helps.
db.collection.aggregate([
{
$group: {
_id: null,
count: {
$sum: "$amount"
}
}
}
])

Sum value of elements and update field Mongo db

How Can I sum price on array "Elemets" and set on Document field Value?
I know how to do It in sql but I,m beginner in mongo.
{
"Document": [
{
"Id": 1,
"Type": "FV",
"Number": 34521,
"Year": 2020,
"Date": "2020-01-01T00:00:00",
"Value": 27.68,
"Elements": [
{
"Id": 1,
"DocumentId": 1,
"ProductId": 1,
"Quantity": 5.00,
"Price": 17.50,
"Task": 0.23
},
{
"Id": 2,
"DocumentId": 1,
"ProductId": 2,
"Quantity": 3.00,
"Price": 24.50,
"Task": 0.23
},
]
},
If you are using MongoDB 4.2, you can use $reduce to calculate the sum in the pipeline form of update.

MongoDb Query db.<collectionname>.find()

I have this Document for mongodb im working on.
The query i m running is showing no output even though there is
one field with score < 5
{
"address": {
"building": "1007",
"coord": [ -73.856077, 40.848447 ],
"street": "Morris Park Ave",
"zipcode": "10462"
},
"borough": "Bronx",
"cuisine": "Bakery",
"grades": [
{ "date": { "$date": 1393804800000 }, "grade": "A", "score": 2 },
{ "date": { "$date": 1378857600000 }, "grade": "A", "score": 6 },
{ "date": { "$date": 1358985600000 }, "grade": "A", "score": 10 },
{ "date": { "$date": 1322006400000 }, "grade": "A", "score": 9 },
{ "date": { "$date": 1299715200000 }, "grade": "B", "score": 14 }
],
"name": "Morris Park Bake Shop",
"restaurant_id": "30075445"
}
db.rest.find({grades : {"score":{$lt:5}}});
The reason that your query isn't getting the expected result is that you're not quite using the correct syntax for querying a field in an embedded document. The correct syntax is
db.rest.find({ "grades.score" : {$lt:5}})
This syntax uses the dot notation to specify the path to the field in the embedded document that you are querying for.
The syntax you used means something a tad different. It queries for a document that has an embedded document which is an exact match to the document in your query rather than looking for a document that has an embedded document with a field in it that matches your search criteria.
To illustrate the difference, let's assume you also have the following document in the collection.
{
"address": {
"building": "1007",
"coord": [ -73.856077, 40.848447 ],
"street": "Morris Park Ave",
"zipcode": "10462"
},
"borough": "Bronx",
"cuisine": "Bakery",
"grades": [
{ "score": 2 },
{ "score": 6 },
{ "score": 10 },
{ "score": 9 },
{ "score": 14 }
],
"name": "Morris Park Bake Shop",
"restaurant_id": "30075445"
}
If we now run the following query, it finds the second document, and only the second document:
db.rest.find({grades : {"score":2}})
This is because this type of query translates the embedded document you specified as the search criterion into its BSON representation and then looks for an exact match to the supplied document rather than apply the criterion you were looking for to every embedded document that has a 'score' field.
If run the query using the

select documents grouped by field

I have this documents of movie showing time and date:
`{
"_id": ObjectId("5628668c3e82c49245b7acdc"),
"ticketID": ObjectId("5606d36b5fbd7d76028b4b08"),
"uid": "50000",
"day": "Friday",
"date": "2015-10-23 21:05:00",
"adult": NumberLong(550),
"student": NumberLong(550),
"children": NumberLong(250),
"limit": NumberLong(20),
"sold": NumberLong(0)
},{
"_id": ObjectId("562866013e82c49045b7acdc"),
"ticketID": ObjectId("5606d36b5fbd7d76028b4b08"),
"uid": "50000",
"day": "Friday",
"date": "2015-10-23 19:30:00",
"adult": NumberLong(1050),
"student": NumberLong(800),
"children": NumberLong(550),
"limit": NumberLong(20),
"sold": NumberLong(0)
},{
"_id": ObjectId("562865013e82c49845b7acda"),
"ticketID": ObjectId("5606d36b5fbd7d76028b4b08"),
"uid": "50000",
"day": "Friday",
"date": "2015-10-23 18:45:00",
"adult": NumberLong(1500),
"student": NumberLong(750),
"children": NumberLong(750),
"limit": NumberLong(20),
"sold": NumberLong(0)
}
`
I want to group the final result by "day" where "ticketID" matches, "date" as an object and adding "adult","student","children","limit" to an array
-- UPDATE --
I would like the returned structure to follow:
{
"_id": "ticketID",
"day": "Friday",
"items": [
{
"date": date,
"time": time"adult": price,
"children": price,
"student": price,
"limit": value
},
{
"date": date,
"time": time"adult": price,
"children": price,
"student": price,
"limit": value
},
{
"date": date,
"time": time"adult": price,
"children": price,
"student": price,
"limit": value
}
]
}
Run the following aggregation pipeline which uses the $group operator to group your documents by the specified fields, add the items array by using the accumulator operator $push that returns an array of expression values for each group. The $project pipeline operator then reshapes the documents by amending the fields to get the final desired structure:
var pipeline = [
{
"$group": {
"_id": {
"ticketID": "$ticketID",
"day": "$day"
},
"items": {
"$push": {
"date": "$date",
"time": "$time",
"adult": "$adult",
"children": "$children",
"student": "$student",
"limit": "$limit"
}
}
}
},
{
"$project": {
"_id": "$_id.ticketID",
"day": "$_id.day",
"items": 1
}
}
];
db.collection.aggregate(pipeline);