compare date with mongoose timestamps using aggregate - node.js

This is the schema:
const mongoose = require("mongoose");
const OrderSchema = mongoose.Schema({
order_status: {
type: "String",
enum: ['Pending', 'Declined', 'Approved','Paid', 'Complete'],
default: "Pending",
},
},{ timestamps: true });
module.exports = mongoose.model("order", OrderSchema);
Stored data in db:
[
{
"_id": "61ceb03b76ed7e3b809bb15b",
"order_status": "Declined",
"createdAt": "2021-12-31T07:24:43.129Z",
"updatedAt": "2021-12-31T07:24:43.129Z",
"__v": 0
},
{
"_id": "61ceb04676ed7e3b809bb15e",
"order_status": "Paid",
"createdAt": "2021-12-31T00:00:00.000Z",
"updatedAt": "2021-12-31T07:24:54.951Z",
"__v": 0
},
{
"_id": "61ceb04f76ed7e3b809bb161",
"order_status": "Approved",
"createdAt": "2022-01-01T00:00:00.000Z",
"updatedAt": "2021-12-31T07:25:03.860Z",
"__v": 0
},
{
"_id": "61ceb05276ed7e3b809bb164",
"order_status": "Complete",
"createdAt": "2021-12-31T07:25:06.580Z",
"updatedAt": "2021-12-31T07:25:06.580Z",
"__v": 0
},
{
"_id": "61ceb05576ed7e3b809bb167",
"order_status": "Complete",
"createdAt": "2021-12-31T07:25:09.686Z",
"updatedAt": "2021-12-31T07:25:09.686Z",
"__v": 0
},
{
"_id": "61ceb06976ed7e3b809bb16d",
"order_status": "Complete",
"createdAt": "2021-12-31T07:25:29.569Z",
"updatedAt": "2021-12-31T07:25:29.569Z",
"__v": 0
},
{
"_id": "61ceb06d76ed7e3b809bb170",
"order_status": "Complete",
"createdAt": "2021-12-31T07:25:33.858Z",
"updatedAt": "2021-12-31T07:25:33.858Z",
"__v": 0
},
{
"_id": "61ceb07376ed7e3b809bb173",
"order_status": "Pending",
"createdAt": "2021-12-31T07:25:39.270Z",
"updatedAt": "2021-12-31T07:25:39.270Z",
"__v": 0
},
{
"_id": "61ceb07776ed7e3b809bb176",
"order_status": "Complete",
"createdAt": "2021-12-31T07:25:43.672Z",
"updatedAt": "2021-12-31T07:25:43.672Z",
"__v": 0
},
{
"_id": "61ceb07e76ed7e3b809bb179",
"order_status": "Complete",
"createdAt": "2021-12-31T07:25:50.963Z",
"updatedAt": "2021-12-31T07:25:50.963Z",
"__v": 0
},
{
"_id": "61ceb08276ed7e3b809bb17c",
"order_status": "Pending",
"createdAt": "2021-12-31T07:25:54.675Z",
"updatedAt": "2021-12-31T07:25:54.675Z",
"__v": 0
},
{
"_id": "61ceb08776ed7e3b809bb17f",
"order_status": "Complete",
"createdAt": "2021-12-31T07:25:59.616Z",
"updatedAt": "2021-12-31T07:25:59.616Z",
"__v": 0
},
{
"_id": "61ceb08d76ed7e3b809bb182",
"order_status": "Complete",
"createdAt": "2021-12-31T07:26:05.141Z",
"updatedAt": "2021-12-31T07:26:05.141Z",
"__v": 0
}
]
Query: the value of from = 2021-01-01T00:00:00.000Z and to = 2021-12-31T00:00:00.000Z
let from = new Date("2021-01-01")
let to = new Date("2021-12-31")
return await OrderSchema.aggregate([
{$match : { createdAt: {
$gte: from, $lte: to
} }
}
])
Using the above query I'm getting no record. when I change the time from createdAt: "2021-12-31T07:26:05.141Z" to createdAt: "2021-12-31T00:00:00.000Z" in DB then it work fine.
How can I get records of 1 month or 1 week from the current date and resolve the time issue?

I think this work for you may be or click here and check results
2022-01-01 --> $lte higher date so set less then
2021-12-31 --> $gte lower date so set grater then
db.collection.aggregate([
{
$match: {
$and: [
{
createdAt: {
$gte: "2021-12-31T00:00:00.000Z"
}
},
{
createdAt: {
$lte: "2022-01-01T00:00:00.000Z"
}
}
]
}
}
])

I believe you need the $and operator:
OrderSchema.aggregate([{
$match : {
$and: {
createdAt: { $gte: from },
createdAt: { $lte: to }
}
}
])

Related

Why $or is not working properly in mongoose with regular expression

I'm trying to fetch documents which contain whatever I pass in url for filter which must present in title field or in tasks array of those documents:
example: localhost:4000/search?filter=Morning. here I'm looking for documents which contain Morning in their title or in their tasks.
But when I'm hitting the Api it is returning me all the documents.
{
"success": true,
"message": "Successfully fetched todos",
"filteredArray": [
{
"_id": "6386e34e2c65763cf25008f3",
"toDoTitle": {
"title": "Morning routines",
"_id": "6386e34e2c65763cf25008f4",
"createdAt": "2022-11-30T04:59:58.940Z",
"updatedAt": "2022-11-30T04:59:58.940Z"
},
"toDoTasks": {
"tasks": [
"code",
"sleep",
"code",
"eat",
"code"
],
"_id": "6386e34e2c65763cf25008f5",
"createdAt": "2022-11-30T04:59:58.941Z",
"updatedAt": "2022-11-30T04:59:58.941Z"
},
"createdAt": "2022-11-30T04:59:58.941Z",
"updatedAt": "2022-11-30T04:59:58.941Z",
"__v": 0
},
{
"_id": "6386e3552c65763cf25008f7",
"toDoTitle": {
"title": "Morning",
"_id": "6386e3552c65763cf25008f8",
"createdAt": "2022-11-30T05:00:05.813Z",
"updatedAt": "2022-11-30T05:00:05.813Z"
},
"toDoTasks": {
"tasks": [
"code",
"sleep",
"code",
"eat",
"code"
],
"_id": "6386e3552c65763cf25008f9",
"createdAt": "2022-11-30T05:00:05.813Z",
"updatedAt": "2022-11-30T05:00:05.813Z"
},
"createdAt": "2022-11-30T05:00:05.813Z",
"updatedAt": "2022-11-30T05:00:05.813Z",
"__v": 0
},
{
"_id": "6386e35f2c65763cf25008fb",
"toDoTitle": {
"title": "evening",
"_id": "6386e35f2c65763cf25008fc",
"createdAt": "2022-11-30T05:00:15.809Z",
"updatedAt": "2022-11-30T05:00:15.809Z"
},
"toDoTasks": {
"tasks": [
"code",
"sleep",
"code",
"eat",
"code"
],
"_id": "6386e35f2c65763cf25008fd",
"createdAt": "2022-11-30T05:00:15.809Z",
"updatedAt": "2022-11-30T05:00:15.809Z"
},
"createdAt": "2022-11-30T05:00:15.810Z",
"updatedAt": "2022-11-30T05:00:15.810Z",
"__v": 0
},
{
"_id": "6386e3672c65763cf25008ff",
"toDoTitle": {
"title": "evening",
"_id": "6386e3672c65763cf2500900",
"createdAt": "2022-11-30T05:00:23.977Z",
"updatedAt": "2022-11-30T05:00:23.977Z"
},
"toDoTasks": {
"tasks": [
"code"
],
"_id": "6386e3672c65763cf2500901",
"createdAt": "2022-11-30T05:00:23.977Z",
"updatedAt": "2022-11-30T05:00:23.977Z"
},
"createdAt": "2022-11-30T05:00:23.977Z",
"updatedAt": "2022-11-30T05:00:23.977Z",
"__v": 0
},
{
"_id": "6386e3712c65763cf2500903",
"toDoTitle": {
"title": "night",
"_id": "6386e3712c65763cf2500904",
"createdAt": "2022-11-30T05:00:33.286Z",
"updatedAt": "2022-11-30T05:00:33.286Z"
},
"toDoTasks": {
"tasks": [
"code"
],
"_id": "6386e3712c65763cf2500905",
"createdAt": "2022-11-30T05:00:33.286Z",
"updatedAt": "2022-11-30T05:00:33.286Z"
},
"createdAt": "2022-11-30T05:00:33.287Z",
"updatedAt": "2022-11-30T05:00:33.287Z",
"__v": 0
}
]
}
This is my model
const mongoose = require("mongoose");
const schema = mongoose.Schema;
const title = new schema(
{
title:{
type: String,
trim: true
}
},
{
timestamps: true
}
);
const task = new schema(
{
tasks:[{ type: String,trim: true}]
},
{
timestamps: true
}
)
const toDoSchema = new schema({
toDoTitle : title,
toDoTasks: task
},
{
timestamps: true
});
const toDoModel = mongoose.model("toDo", toDoSchema);
module.exports = toDoModel;
this is my controller for filtering:
//importing model
const toDoModel = require('../models/ToDoModel');
//importing utils function
const toDosPerPage = require("../utlis/ToDosPerPage")
const searchController = async (req,res)=>{
try{
const {filter} = req.query
if(!filter) throw new Error("Please provide Something in filter to search");
const filteredArray = await toDoModel.find({
$or:[{title:new RegExp(filter,'i')},{tasks: new RegExp(filter,'i')}]
});
res.status(200).json({
success: true,
message: "Successfully fetched todos",
filteredArray
});
}
catch(err){
res.status(401).json({
success: false,
message: "Some error occuried",
error: err.message
})
console.log(err.message);
}
}
module.exports = searchController;
I want it to return only those documents which contain morning in their title or in their tasks fields.
to find in embeded document use dot .
const filteredArray = await toDoModel.find({
$or:[
{'toDoTitle.title':new RegExp(filter,'i')},
{'toDoTasks.tasks':new RegExp(filter,'i')}
]
});

Select by category and count by status mongodb

I have a list of records and want to group by categories and after this count buy isArchived status.
I'm just starting to learn MongoDB and I can't do the query described below, I would appreciate your tips.
This is peace of data.
[
{
"_id": "63356af2d77a56d764f362e4",
"noteName": "string",
"category": "IDEA",
"content": "string",
"isArchived": true,
"createdAt": "2022-09-29T09:52:50.477Z",
"updatedAt": "2022-09-29T09:52:50.477Z",
"__v": 0
},
{
"_id": "63356afad77a56d764f362ea",
"noteName": "string",
"category": "IDEA",
"content": "string",
"isArchived": false,
"createdAt": "2022-09-29T09:52:58.765Z",
"updatedAt": "2022-09-29T09:52:58.765Z",
"__v": 0
},
{
"_id": "63356afbd77a56d764f362ee",
"noteName": "string",
"category": "IDEA",
"content": "string",
"isArchived": false,
"createdAt": "2022-09-29T09:52:59.180Z",
"updatedAt": "2022-09-29T09:52:59.180Z",
"__v": 0
},
{
"_id": "63356b04d77a56d764f362f4",
"noteName": "string",
"category": "TASK",
"content": "string",
"isArchived": false,
"createdAt": "2022-09-29T09:53:08.261Z",
"updatedAt": "2022-09-29T09:53:08.261Z",
"__v": 0
},
{
"_id": "63356b09d77a56d764f362fc",
"noteName": "string",
"category": "TASK",
"content": "string",
"isArchived": true,
"createdAt": "2022-09-29T09:53:13.980Z",
"updatedAt": "2022-09-29T09:53:13.980Z",
"__v": 0
},
{
"_id": "63356b0ad77a56d764f362fe",
"noteName": "string",
"category": "TASK",
"content": "string",
"isArchived": true,
"createdAt": "2022-09-29T09:53:14.445Z",
"updatedAt": "2022-09-29T09:53:14.445Z",
"__v": 0
}]
This is request
getStats() {
const stats = this.noteModel
.aggregate([
{
$group: {
_id: {
category: '$category',
isArchived: '$isArchived',
},
count: {
$sum: 1,
},
},
},
{ $sort: { _id: 1 } },
])
.project({
_id: 0,
category: '$_id.category',
isArchived: '$_id.isArchived',
average: 1,
count: '$count',
});
return stats;
}
Now I receive like this
[
{
"category": "IDEA",
"isArchived": false,
"count": 5
},
{
"category": "IDEA",
"isArchived": true,
"count": 3
},
{
"category": "QUOTE",
"isArchived": false,
"count": 4
},
{
"category": "QUOTE",
"isArchived": true,
"count": 3
},
{
"category": "RANDOM THOUGHT",
"isArchived": false,
"count": 2
},
{
"category": "RANDOM THOUGHT",
"isArchived": true,
"count": 3
}....
]
But I want to receive it like this
[
{
"category": "IDEA",
"archived": 5,
"unArchived": 3
},
{
"category": "QUOTE",
"archived": 5,
"unArchived": 3
},
{
"category": "RANDOM THOUGHT",
"archived": 2,
"unArchived": 3
},
{
"category": "TASK",
"archived": 3,
"unArchived": 3
},
]
What should be changed in the query to get the required view?
Group by category only and calculate the archived and unArchived counts by checking the condition,
archived condition is if isArchived is true then return 1 otherwise 0
unArchived condition is if isArchived is true then return 0 otherwise 1
const stats = this.noteModel.aggregate([
{
$group: {
_id: "$category",
archived: {
$sum: { $cond: ["$isArchived", 1, 0] }
},
unArchived: {
$sum: { $cond: ["$isArchived", 0, 1] }
}
}
},
{ $sort: { _id: 1 } }
])
Playground

Mongoose aggregate by date and values

I cannot solve a problem I am having on a project.
First of all, I have a Schema called Emotions, shown below:
import mongoose from 'mongoose';
const EmotionSchema = new mongoose.Schema({
classification: {
type: String,
required: true,
},
probability: {
type: Number,
required: true,
},
user: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User',
}
}, {
timestamps: true,
});
export default mongoose.model('Emotion', EmotionSchema);
And some data like this:
[
{
"_id": "61144a393c532f066725bd24",
"classification": "Feliz",
"probability": 0.98,
"user": "60eecfeba0810013e750cdbc",
"createdAt": "2021-08-11T22:07:53.331Z",
"updatedAt": "2021-08-11T22:07:53.331Z",
"__v": 0
},
{
"_id": "61144a46d30bd006fa2be702",
"classification": "Feliz",
"probability": 0.98,
"user": "60eecfeba0810013e750cdbc",
"createdAt": "2021-08-11T22:08:06.618Z",
"updatedAt": "2021-08-11T22:08:06.618Z",
"__v": 0
},
{
"_id": "611541dd62a7f214afab3ceb",
"classification": "Triste",
"probability": 0.9,
"user": "60eecfeba0810013e750cdbc",
"createdAt": "2021-08-12T15:44:29.150Z",
"updatedAt": "2021-08-12T15:44:29.150Z",
"__v": 0
},
{
"_id": "611541f762a7f214afab3cf5",
"classification": "Raiva",
"probability": 0.86,
"user": "60eecfeba0810013e750cdbc",
"createdAt": "2021-08-12T15:44:55.909Z",
"updatedAt": "2021-08-12T15:44:55.909Z",
"__v": 0
},
{
"_id": "6115420362a7f214afab3cf7",
"classification": "Neutro",
"probability": 0.99,
"user": "60eecfeba0810013e750cdbc",
"createdAt": "2021-08-12T15:45:07.297Z",
"updatedAt": "2021-08-12T15:45:07.297Z",
"__v": 0
},
{
"_id": "6115420462a7f214afab3cf9",
"classification": "Neutro",
"probability": 0.99,
"user": "60eecfeba0810013e750cdbc",
"createdAt": "2021-08-12T15:45:08.002Z",
"updatedAt": "2021-08-12T15:45:08.002Z",
"__v": 0
},
{
"_id": "611543d252be9a187c380e5d",
"classification": "Feliz",
"probability": 0.91,
"user": "60eecfeba0810013e750cdbc",
"createdAt": "2021-08-12T15:52:50.599Z",
"updatedAt": "2021-08-12T15:52:50.599Z",
"__v": 0
}
]
What I want is:
First group each of these records by day.
Afterwards, count the values ​​by classification, but separating these classifications.
Something like that:
[
{
"_id": "12/08/2021",
"feliz": 1,
"triste": 1,
"raiva": 1,
"neutro": 2,
"surpreso": 0,
},
{
"_id": "11/08/2021",
"feliz": 2,
"triste": 0,
"raiva": 0,
"neutro": 0,
"surpreso": 0,
}
]
I did something like that, but it's only working for a value, eg "Feliz".
In code:
Emotion.aggregate([
{ $match:
{
user: user._id,
classification: "Feliz"
}
},
{ $group: {
_id : { $dateToString: { format: "%d/%m/%Y", date: "$createdAt" } },
feliz: { $sum: 1 }
}},
], function(err, results) {
if (err) throw err;
return res.json(results);
})
And it returns:
[
{
"_id": "12/08/2021",
"feliz": 1
},
{
"_id": "11/08/2021",
"feliz": 4
}
]
One more question:
From the Client-side, I always get values ​​for "classification" like:
"Feliz", "Triste", "Surpreso", "Raiva", "Neutro".
So is it better to add an enum to my schema "Emotion"?
(Sorry for my English, i hope you understand).
$group by createdAt date and classification, count sum
$group by createdAt only and construct the array of classification and count in key-value pair
$arrayToObject to convert above key-value pair array of object to an object format
Emotion.aggregate([
{
$match: {
user: user._id,
classification: "Feliz"
}
},
{
$group: {
_id: {
createdAt: {
$dateToString: {
format: "%d/%m/%Y",
date: "$createdAt"
}
},
classification: "$classification"
},
count: { $sum: 1 }
}
},
{
$group: {
_id: "$_id.createdAt",
classifications: {
$push: {
k: "$_id.classification",
v: "$count"
}
}
}
},
{
$addFields: {
classifications: {
$arrayToObject: "$classifications"
}
}
}
],
function(err, results) {
if (err) throw err;
return res.json(results);
})
Playground
Note: this will not return classification when count is 0! You need to do this after query in js.
One more question: From the Client-side, I always get values ​​for "classification" like: "Feliz", "Triste", "Surpreso", "Raiva", "Neutro". So is it better to add an enum to my schema "Emotion"?
It is up to your project requirement, you can set these values in enum to restrict the input.

mongodb $addfields conditions is not working

i have used lookup for join 2 tables and i need to create 2 custom column so i have used the $addfields.
In $addfields, Member is not working but pqr is working.
I have a array of objects as a given below :
await mongoose.models.abc.aggregate([
{
$lookup:
{`enter code here`
from: 'xyz',
localField: 'id',
foreignField: '_id',
as: 'my'
}
},
{
$match: {
"my": { $ne: [] }
}
},
{
$addFields: {
pqr: { $cond: [{ $gte: ["$my.request", 1] }, { $sum: "$my.request" }, 0] },
Member: { $cond: [{ $eq: ["$myClub.request", 0] }, { $sum: "$myClub.request" }, 0] },
}
},
]);
[
{
"_id": "5ef05f650e26a40cb44a68d6",
"createdAt": "2020-06-22T07:36:05.640Z",
"updatedAt": "2020-06-22T07:36:05.640Z",
"__v": 0,
"my": [
{
"_id": "5eecc3c961767f21c8d694e0",
"request": 1,
"createdAt": "2020-06-19T13:55:21.573Z",
"updatedAt": "2020-06-19T13:55:21.573Z",
"__v": 0
},
{
"_id": "5ef1b8f2c3d54e21f4d6b332",
"request": 0,
"createdAt": "2020-06-23T08:10:26.036Z",
"updatedAt": "2020-06-23T08:10:26.036Z",
"__v": 0
}
]
}
]
i need a output like this:
[
{
"_id": "5ef05f650e26a40cb44a68d6",
"createdAt": "2020-06-22T07:36:05.640Z",
"updatedAt": "2020-06-22T07:36:05.640Z",
"__v": 0,
"my": [
{
"_id": "5eecc3c961767f21c8d694e0",
"request": 1,
"createdAt": "2020-06-19T13:55:21.573Z",
"updatedAt": "2020-06-19T13:55:21.573Z",
"__v": 0
},
{
"_id": "5ef1b8f2c3d54e21f4d6b332",
"request": 0,
"createdAt": "2020-06-23T08:10:26.036Z",
"updatedAt": "2020-06-23T08:10:26.036Z",
"__v": 0
}
],
"pqr":1, // for greater than eqaul to request=1
"Member":1 // // for eqaul to request=0
}
]

Mongoose sort and get only one per field

I need to get a list of item using the mongoose, however, i need select only one item of any type (i've 5 possible values), and always the last inserted item of this type.
for example, to the list below, not ordered (i know, here it's ordered).
[
{
"_id": "5b226abab64b2309de01bfd5",
"documentType": "type3",
"createdAt": "2018-06-14T13:16:42.321Z"
},
{
"_id": "5b226a5da93b0e09b8aee447",
"documentType": "type3",
"createdAt": "2018-06-14T13:15:09.458Z"
},
{
"_id": "5b226a21f454d6097ffa461c",
"documentType": "type2",
"createdAt": "2018-06-14T13:14:09.159Z"
},
{
"_id": "5b2267fb445d7709590e1695",
"documentType": "type1",
"createdAt": "2018-06-14T13:04:59.742Z"
},
{
"_id": "5b2267de76708b094696b0fe",
"documentType": "type3",
"createdAt": "2018-06-14T13:04:30.349Z"
},
{
"_id": "5b2267ce2f3724092b1a14a3",
"documentType": "type2",
"createdAt": "2018-06-14T13:04:14.410Z"
},
{
"_id": "5b2267a92f3724092b1a14a2",
"documentType": "type4",
"createdAt": "2018-06-14T13:03:37.079Z"
},
{
"_id": "5b22647b63017e08a69a3043",
"documentType": "type5",
"createdAt": "2018-06-14T12:50:03.999Z"
},
{
"_id": "5b2264471778a20880d4ba64",
"documentType": "type5",
"createdAt": "2018-06-14T12:49:11.773Z"
}
]
the expected result is something like this:
[
{
"_id": "5b226abab64b2309de01bfd5",
"documentType": "type3",
"createdAt": "2018-06-14T13:16:42.321Z"
},
{
"_id": "5b226a21f454d6097ffa461c",
"documentType": "type2",
"createdAt": "2018-06-14T13:14:09.159Z"
},
{
"_id": "5b2267fb445d7709590e1695",
"documentType": "type1",
"createdAt": "2018-06-14T13:04:59.742Z"
},
{
"_id": "5b2267a92f3724092b1a14a2",
"documentType": "type4",
"createdAt": "2018-06-14T13:03:37.079Z"
},
{
"_id": "5b22647b63017e08a69a3043",
"documentType": "type5",
"createdAt": "2018-06-14T12:50:03.999Z"
}
]
Basicly only one per type, sort desc by id
How can i do this?
You can use $group by in mongodb to distinct the documentType
db.collection.aggregate([
{ "$group": {
"_id": "$documentType",
"createdAt": { "$first": "$createdAt" },
"id": { "$first": "$_id" }
}},
{ "$project": {
"_id": "$id",
"createdAt": 1,
"documentType": "$_id"
}}
])
The output will be
[
{
"_id": "5b226abab64b2309de01bfd5",
"createdAt": "2018-06-14T13:16:42.321Z",
"documentType": "type3"
},
{
"_id": "5b2267fb445d7709590e1695",
"createdAt": "2018-06-14T13:04:59.742Z",
"documentType": "type1"
},
{
"_id": "5b22647b63017e08a69a3043",
"createdAt": "2018-06-14T12:50:03.999Z",
"documentType": "type5"
},
{
"_id": "5b2267a92f3724092b1a14a2",
"createdAt": "2018-06-14T13:03:37.079Z",
"documentType": "type4"
},
{
"_id": "5b226a21f454d6097ffa461c",
"createdAt": "2018-06-14T13:14:09.159Z",
"documentType": "type2"
}
]

Resources