Find all n days documents in MongoDB - javascript

I've been looking to get data for the last n days. For example, I want to just all the data of the last 3 days. After implementing a solution from another question in StackOverflow I'm not getting all the documents. I am only getting one document. If I want to see the documents for the last 3 days it is only showing data for one particular day.
Here's my Schema:
dayWiseClicks: [
{
date: {
type: Date,
},
dailyClicks: {
type: Number,
default: 0,
},
},
],
Here's the data I have before performing the query:
{
"_id": {
"$oid": "61eff4bacf8335c7013f8065"
},
"dayWiseClicks": [
{
"dailyClicks": 3,
"_id": {
"$oid": "61eff5db5dca56cae4530db2"
},
"date": {
"$date": "2022-01-24T18:00:00.000Z"
}
},
{
"dailyClicks": 4,
"_id": {
"$oid": "61eff60b5dca56cae4530db6"
},
"date": {
"$date": "2022-01-25T18:00:00.000Z"
}
},
{
"dailyClicks": 2,
"_id": {
"$oid": "61eff64a5dca56cae4530dba"
},
"date": {
"$date": "2022-01-26T18:00:00.000Z"
}
},
{
"dailyClicks": 7,
"_id": {
"$oid": "61f60ce51f14b01f8f5be936"
},
"date": {
"$date": "2022-01-29T18:00:00.000Z"
}
},
{
"dailyClicks": 11,
"_id": {
"$oid": "61f7b1d3931b0f8bc33703d4"
},
"date": {
"$date": "2022-01-30T18:00:00.000Z"
}
},
{
"dailyClicks": 8,
"_id": {
"$oid": "61f8bdf63cc3a51b72474cb9"
},
"date": {
"$date": "2022-01-31T18:00:00.000Z"
}
},
{
"dailyClicks": 7,
"_id": {
"$oid": "61fba7159692624ce8ea04d6"
},
"date": {
"$date": "2022-02-02T18:00:00.000Z"
}
}
],
}
In theory, if I want to see the last 3 days of data. It should be showing data of 31st Jan, 2nd February but It is only showing Data of 31st January.
Here's the data I am getting:
{
"message": "Url By ID",
"result": {
"_id": "61eff4bacf8335c7013f8065",
"dayWiseClicks": [
{
"dailyClicks": 8,
"_id": "61f8bdf63cc3a51b72474cb9",
"date": "2022-01-31T18:00:00.000Z"
}
]
}
}
Here's my Code:
exports.lastNDays = async (req, res) => {
try {
const url = await URL.findById(
{ _id: req.params.id },
{
dayWiseClicks: {
$elemMatch: {
date: {
$gte: moment().add(-3, "days"),
},
},
},
}
)
return res.status(200).json({
message: "Url By ID",
result: url,
});
} catch (error) {
return res.status(404).json({ error: error.message });
}
};
Can any one tell me exactly where I am making the mistake?

The aggregation->$filter option seems more suitable for the task , example:
db.collection.aggregate([{
$match: {
"_id": {
"$oid": "61eff4bacf8335c7013f8065"
}
}
},
{
$project: {
dayWiseClicks: {
$filter: {
input: "$dayWiseClicks",
as: "item",
cond: {
$gte: [
"$$item.date",
{
"$date": "2022-01-30T18:00:00.000Z"
}
]
}
}
}
}
}
])
Explained:
$match single document by _id
$filter only the dayWiseClicks greater or equal to certain date.
playground

If your dayWiseClicks are in natural date-ascending order (and it seems that way), then to generically capture the last 3 days of any sequence of dates can be done with $slice:
db.foo.aggregate([
{$addFields: {dayWiseClicks: {$slice: ["$dayWiseClicks", -3]}}}
]);
You can prepend $match stages as detailed in previous answers.
NOTE: Coming up in v5.4 (available now in 5.2 rapid release for MongoDB Atlas) is the long-awaited sortArray operator. If the dayWiseClicks was not in date order, then making it that way and finding the last 3 dates is freshingly simple:
db.foo.aggregate([
{$addFields: {dayWiseClicks: {$slice: [{$sortArray:{input: "$dayWiseClicks", sortBy: {"date":1}}, -3]}}}
]);
Similarly, to get the last 3 dates but in descending order:
db.foo.aggregate([
{$addFields: {dayWiseClicks: {$slice: [{$sortArray:{input: "$dayWiseClicks", sortBy: {"date":-1}}, 3]}}}
]);

Related

MongoDB refuses to insert data

I have been trying to insert a piece of data in my db collection, mys chema looks like this
{
"_id": {
"$oid": "62d30157607575f6be6ce948"
},
"semester": "sem-5",
"subjectData": {
"subjectName": "eco",
"questionBank": [{
"question": "who are",
"answer": {
"introduction": "Hello my name is Izaan",
"features": ["tall", "handsome"],
"kinds": ["very", "kind"],
"conclusion": "Mighty man",
"_id": {
"$oid": "62d30157607575f6be6ce94b"
}
},
"_id": {
"$oid": "62d30157607575f6be6ce94a"
}
}],
"_id": {
"$oid": "62d30157607575f6be6ce949"
}
},
"__v": {
"$numberInt": "0"
}
}
And I would like to insert some questions and answers depending on semester and subject, first I want to query for the semester and then subject and then insert data without deleting prev data in the questionBank array
Here is how I am doing this and which is giving all kinds of error and still I have not managed to get the desired result
// IF DATA EXISTS UPDATE QUESTIONSBANK WITHOUT DELETING ANY ITEMS
try {
const result = await semesterData.update({
semester: {
$eq: semesterRecieved
},
subjectName: {
$eq: subject
},
}, {
$push: {
question: questionRecieved,
answer: answerRecieved2,
},
}, );
res.send(result);
} catch (error) {
console.log(error);
res.status(404).send(error.message);
}
}

How to sum item in transaction subdocument mongodb from other document relationship

I'm new in mongodb and try small project and document are design just like below
products
[
{
_id:ObjectId('60d87d6fafd7a1377c03b2e6'),
productName:"noodles instant",
description:"lorem ipsum ... ... ...."
},
{
_id:ObjectId('60d87d6fafd7a1377c03b2e7'),
productName:"Sandal",
description:"lorem ipsum ... ... ...."
}
]
and my transaction document has structure is just like below
transactions
[
{
_id:ObjectId('60d8781031308dbf565eaaa8'),
trasactionSerial:"TRS20210000001",
transactionDate:2021-06-27T13:30:23.369+00:00,
productInTransactions:[
{
_id:ObjectId('60d8781031308dbf565eaab9'),
productId:ObjectId('60d87d6fafd7a1377c03b2e6'),
qty:1500
},
{
_id:ObjectId('60d8781031308dbf565eaa47'),
productId:ObjectId('60d87d6fafd7a1377c03b2e7'),
qty:200
}
]
},
{
_id:ObjectId('60d8781031308dbf565eaab7'),
trasactionSerial:"TRS20210000002",
transactionDate:2021-06-27T13:32:23.369+00:00,
productInTransactions:[
{
_id:ObjectId('60d8781031308dbf565eaab9'),
productId:ObjectId('60d87d6fafd7a1377c03b2e6'),
qty:100
},
{
_id:ObjectId('60d8781031308dbf565eaa47'),
productId:ObjectId('60d87d6fafd7a1377c03b2e7'),
qty:300
}
]
}
]
from the transaction I hope will get some result like below from the same date in transactionDate field
result
[
{
_id:ObjectId('60d87d6fafd7a1377c03b2e6'),
productName:"noodles instant",
qtyInTransaction:1600
},
{
_id:ObjectId('60d87d6fafd7a1377c03b2e7'),
productName:"Sandal",
qtyInTransaction:500
},
]
sorry maybe my English is poor to elaborate it
thanks for any feedback and your help
Use the $lookup stage which has $group in its pipeline option.
db.products.aggregate([
{
"$lookup": {
"from": "transactions",
"let": {
"pId": "$_id"
},
"pipeline": [
{
"$unwind": "$productInTransactions"
},
{
"$match": {
"$expr": {
"$eq": [
"$productInTransactions.productId",
"$$pId"
]
},
},
},
{
"$group": {
"_id": "$$pId",
"qtyInTransaction": {
"$sum": "$productInTransactions.qty"
}
},
},
],
"as": "matchedTransactions"
}
},
{
"$project": {
"_id": 1,
"description": 1,
"qtyInTransaction": {
"$arrayElemAt": [
"$matchedTransactions.qtyInTransaction",
0
]
}
},
},
])
Mongo Playground Sample Execution

getting error unknown group operator '$group' in mongoDB

I am trying to count distinct(not unique) or Emp No in same department.but getting error
query failed: unknown group operator '$group'
here is my code
https://mongoplayground.net/p/UvYF9NB7vZx
db.collection.aggregate([
{
$group: {
_id: "$Department",
total: {
"$group": {
_id: "$Emp No"
}
}
}
}
])
Expected output
[
{
"_id": "HUAWEI”,
“total”:1
},
{
"_id": "THBS”,
“total”:2
}
]
THBShave two different Emp No A10088P2C and A20088P2C
HUAWEI have only one Emp No A1016OBW
so, $group is Pipeline stage, you can only use it in upper level.
But for your required output there is lots of ways i believe,
we can do something like this as well:
db.collection.aggregate([
{
$group: {
_id: {
dept: "$Department",
emp: "$Emp No"
},
total: {
"$sum": 1
}
}
},
{
$group: {
_id: "$_id.dept",
total: {
"$sum": 1
}
}
}
])
Here, in first stage we are grouping with Department and its Emp No , and also we are having count of how many Emp No is in each dept.
[this count you can remove though as we are not using it.]
result of this stage will be:
[
{
"_id": {
"dept": "THBS",
"emp": "A10088P2C"
},
"total": 2
},
{
"_id": {
"dept": "THBS",
"emp": "A20088P2C"
},
"total": 1
},
{
"_id": {
"dept": "HUAWEI",
"emp": "A1016OBW"
},
"total": 3
}
]
next on top of this part data, i'm grouping again, with the dept. which comes in $_id.dept, and making count in the same way, which gives the result in your required format.
[
{
"_id": "HUAWEI",
"total": 1
},
{
"_id": "THBS",
"total": 2
}
]
Demo

How can I count the documents in an array depending on their value in mongodb?

I need to count the number of parking spaces _id: 5d752c544f4f1c0f1c93eb23, which has the false value in the excluded property, how can I mount the query?
So far, I've been able to select the number of parking spaces with the excluded: false property. But are selecting from all parking lots
Note that there are two documents symbolizing a parking lot, where each has an array, called parkingSpaces, to record parking space documents.
The first document has 2 vacancies not excluded, so with the property excluded: false and the second has only one vacancy, which is not excluded either.
{
"_id": "5d752c544f4f1c0f1c93eb23",
"name": "estacionamento um",
"parkingSpace": [
{
"_id": "5d752cf54f4f1c0f1c93eb26",
"name": "vg001",
"excluded": true
},
{
"_id": "5d752cf54f4f1c0f1c93eb27",
"name": "vg001",
"excluded": false
},
{
"_id": "5d75339bc411423a9c14ac52",
"name": "vg002",
"excluded": false
}
]
},
{
"_id": "5d7706b60d354b72388a38f4",
"name": "estacionamento dois",
"parkingSpace": [
{
"_id": "5d77078a5173bb63bc87b7ca",
"name": "vg004",
"excluded": false
}
]
}
I need to add the number of parking spaces _id: 5d752c544f4f1c0f1c93eb23, which has the value false in the excluded property.
In the end, I need to return the value 2, referring to _id: 5d752c544f4f1c0f1c93eb23 parking spaces, which have the value false in the excluded property.
So far, with the following query, I was able to select the vacancies with the excluded property with the false value, but it is selecting from all parking lots.
const registeredParkingSpaces = await Parking.aggregate([
{ $unwind: '$parkingSpace' },
{ $match: { 'parkingSpace.excluded': false } },
{
$group: {
_id: parking_id,
total: { $sum: 1 }
}
}
]);
returns:
{
"message": [
{
"_id": "5d752c544f4f1c0f1c93eb23",
"total": 3
}
]
}
But it needs to return:
{
"message": [
{
"_id": "5d752c544f4f1c0f1c93eb23",
"total": 2
}
]
}
In aggregation 1st you match with id then go for the next step you will get your desire count because at this moment you are considering entire document "parkingSpace". Below is the sample code I guess it will work for you
const ObjectId = require('mongoose').Types.ObjectId;
const registeredParkingSpaces = await Parking.aggregate([
{ $match: { _id: objectId(body.id) } }
{ $unwind: '$parkingSpace' },
{ $match: { 'parkingSpace.excluded': false } },
{
$group: {
_id: parking_id,
total: { $sum: 1 }
}
}
]);
This is the query through which you can get the count of total parking .
** UPDATED **
db.collection.aggregate([
{
$match: {
"parkingSpace.excluded": false,
}
},
{
$project: {
parkingSpace: 1
}
},
{
"$group": {
"_id": "$_id",
"count": {
"$sum": {
"$size": {
"$filter": {
"input": "$parkingSpace",
"as": "el",
"cond": {
"$eq": [
"$$el.excluded",
false
]
}
}
}
}
}
}
}
])
You can check the solution from this LINK
For more information about $sum : Visit the official official document
Through this you get your solution .

How can i push values of a specific field with mongoose aggregate

I am using this code inside a route:
MyModel.aggregate(
[
{ "$group": {
"_id": "$date",
"participants": { "$sum": "$participants" },
"peoples": { $sum: 1 }
}
},
],
function(err, result) {
console.log(result)
}
......etc......
This is aggregating the date, participants and peoples, but i want access the name field, and i was trying like this:
"_id": "$date",
"name": "$name",
"participants": { "$sum": "$participants" },
"peoples": { $sum: 1 }
but is returning:
{ [MongoError: exception: the group aggregate field 'name' must be defined as an expression inside an object]
name: 'MongoError',
errmsg: 'exception: the group aggregate field \'some\' must be defined as an expression inside an object',
code: 15951,
ok: 0 }
What i am doing wrong?
You need the $first operator for this. ie.:
MyModel.aggreagate(
[
{ "$group": {
"_id": "$date",
"name": { "$first": "$name" },
"participants": { "$sum": "$participants" },
"peoples": { "$sum": 1 }
},
],
function(err,results) {
// rest of processing.
}
);
Suspect that your "peoples" and "participants" fields are also wrong. But that's another question out of context here.

Categories

Resources