I have the following sub-documents :
{
id: 1,
date:2019-04-01 00:21:19.000
},
{
id: 2,
date:2019-03-31 00:21:19.000
} ...
Document schema is :
const barEventSchema = new Schema({
id: {
type: Number,
unique: true,
required: true
},
raw: { type: String },
date: { type: Date },
type: { type: String },
})
const FooSchema = new Schema({
bar: [barEventSchema]
})
I want to do a query based on a date range picked from html input, which has values like 2019-04-01, 2019-03-31.
So on serverside, I want to do something like:
//#star_date = 2019-04-01, #end_date = 2019-04-01
Foo.findOne('bar.date' : {$lte : start_date, $gte: end_date})
However, this returns all the documents.
All documents having any subdocument with date between start and end date range can be retrieved using:
const conditions = {
'bar': {
$elemMatch: {
'date': {
$gte: new Date(start_date),
$lte: new Date(end_date)
}
}
}
}
Foo.find(conditions)
This will return all the documents where there is at least a subdocument having its date between the range specified in condition.
The $elemMatch operator is used to effect this condition on the date field of the bar subdocument.
Related
I have this model:
const HistorySchema = new Schema({
// Other fields
date: {
type: Date,
default: Date.now,
},
});
I am using an aggregate query to get some data and trying to format the date in the same time:
const final_project_option = {
$project: {
// Other projections
date: {
$dateFromString: {
date: "$date",
},
},
},
};
const pipeline = [
// Other options
final_project_option,
];
const history_events_with_aggregate = await History.aggregate(pipeline);
But, I am receiving this error:
error MongoError: $dateFromString requires that 'dateString' be a
string, found: date with value 2021-07-06T12:24:45.707Z
Any idea what's going on?
I need to take array from my model, delete from it some days and push to it some other days. It looks something like deleteAndUpdate.
To sum up:
I need to take Car from database. Take reserved property (it's a array), then delete from reserved days from given list, and then add to reserved days from other given list.
My model look:
const CarSchema = mongoose.Schema({
mark:{
type: String,
required: true,},
model:{
type: String,
required: true,},
price:{
type: Number,
required: true,},
available: {
type: Boolean,
required: true,},
reserved:{
type:[Date],
},
pic_1:{
type:String,
required:true,
},
pic_2:{
type:String,
required:true,
},
},
{ collection: 'cars' }
)
I take car by: var car= await Car.findById(carID); and then i need to do sth like that:
car['reserved'].deleted(old_days);
car['reserved'].push(new_days;
car.save();
Could someone help me?
Update can't allow multiple operation at a time in same field, It will throw multiple write error and would create a conflict at your field,
Regular update:
If you want to do it by regular update query you have to do separate do 2 queries,
Delete days: If you want to delete multiple days use $pullAll, and for single you can use $pull
var old_days = [new Date("2021-04-24"), new Date("2021-04-25")];
await Car.updateOne({ _id: carID }, { $pullAll: { reserved: old_days } });
Add days: if you want to add multiple days you can use $push with $each, and for single you can use just $push,
var new_days = [new Date("2021-04-26"), new Date("2021-04-27")];
await Car.updateOne({ _id: carID }, { $push: { reserved: { $each: new_days } } });
Update with aggregation pipeline:
If you are looking for single query you can use update with aggregation pipeline starting from MongoDB 4.2,
$filter to iterate loop of reserved array and remove old days
$concatArrays to concat reserved array with new days
var old_days = [new Date("2021-04-24"), new Date("2021-04-25")];
var new_days = [new Date("2021-04-26"), new Date("2021-04-27")];
await Car.updateOne(
{ _id: carID },
[{
$set: {
reserved: {
$filter: {
input: "$reserved",
cond: { $not: { $in: ["$$this", old_days] } }
}
}
}
},
{
$set: {
reserved: {
$concatArrays: ["$reserved", new_days]
}
}
}]
);
Playground
To remove old item from array you can use $pull
car.update(
{ _id: carID },
{ $pull: { 'reserved': old_days } }
);
You can use $unset to unset the value in the array (set it to null), but not to remove it completely.
To add the item new_days in array, You can either use $push or $addToSet
car.update(
{ _id: carID },
{ $push: { 'reserved': new_days } }
);
I need to get each user's transactions every three days. I want to know users that don't have up to a certain amount(200) within the three days period, then get the sum of all the transactions for each user. I want to exclude Sunday since transactions are always low on Sundays.
I want to make sure this is done right from the DB because the transactions from each user can run into thousands even millions.
I am using dayjs to manipulate the time but I am not getting it right
I have been able to get the three previous date and the current date. The previous date will be the startDate and the current date will be endDate.
But I need to remove if Sunday is in the range and use that to query the database.
This is what I have done what I am not close to fixing it.
How can I query the transaction table by dateCreated and exclude sundays?
schema sample
export const TransactionSchema = new mongoose.Schema({
description: {
type: String
},
ref: {
type: String,
required: true
},
userID: {
type: mongoose.SchemaTypes.ObjectId,
ref: 'User'
},
amount: {
type: Number,
required: true,
},
commission: {
type: Number,
default: 0
},
responseDescription: {
type: String
},
authCode: {
type: Number
},
isDeleted: {
type: Boolean,
default: false
},
dateCreated: {
type: Date,
default: Date.now
},
dateUpdated: {
type: Date,
required: false
},
openingBalance: {
type: Number
},
closingBalance: {
type: Number
},
})
method
async getUserRequiredTargetTrans() {
let now = dayjs();//endDate
let fromThreeDays = now.subtract('2', 'day')
let sunday = now.day(0)
let withOutSunday = now.diff(fromThreeDays);//startDate
const response = await this.transactionModel.find({ isDeleted: false, dateCreated: { $gte: withOutSunday, $lt: now } })
To exclude sundays from date range, you can use $where operator like this:
async getUserRequiredTargetTrans() {
let from = dayjs();//endDate
let fromThreeDays = now.subtract('2', 'day')
const response = await this.transactionModel.find({ isDeleted: false, dateCreated: { $gte: fromThreeDays, $lt: now },
// exculde sunday
$where: `function() { return this.dateCreated.getDay() !== 0;}`
} )
You pass a dayjs, don't know whether you can use it directly. Perhaps you have to use
find({ isDeleted: false, dateCreated: { $gte: withOutSunday.toDate(), $lt: now.toDate() } })
So I have a collection in which I dump logs.Each log have EndUserId field.
The mongoose schema is as follows:
var mongoose = require("mongoose");
var Schema = mongoose.Schema;
var ChatbotLogsSchema = new Schema({
EndUserId: {
type: String
},
MessageType: {
type: String
},
Message:{
type: String
},
CreatedDateTime: {
type: Date, default: Date.now
},
UpdatedDateTime: {
type: Date, default: Date.now
},
SentimentScore: {
type: Number
},
EngageWeight: {
type: Number
}
}, { timestamps: { createdAt: 'CreatedDateTime',updatedAt:"UpdatedDateTime" } },{ collection: "ChatbotLogs" });
I want to get list of distinct EndUserId which are logged in last 5 minutes and were not present in collection previously.
What will be the efficient way to achieve this?
Edit :This question is different than Query to get last X minutes data with Mongodb
As I want to get only new users which were not present previously in collection.
I want to create a DB Schema to store the data as below
{
name : "xyz",
admin : "admin",
expense : [
jan: [{expenseObject},{expenseObject}],
feb: [[{expenseObject},{expenseObject}]
]
}
Expense Object
var expenseSchema = new Schema({
particular : String,
date : {type : Date, default: Date.now},
paid_by : String,
amount : Number
});
Can someone help me create a schema for the same.
Any suggestions for a better Schema for the same concept are welcome.
You can use Sub Docs
var parentSchema = new Schema({
name: { type: String },
admin: { type: String },
expense: [expenseSchema]
});
Or, if you need the expenseObjects to be stored in a seperate collection you can use refs, where Expense would be the name of another model
var parentSchema = new Schema({
name: { type: String },
admin: { type: String },
expense: [{ type: Schema.Types.ObjectId, ref: 'Expense' }],
});
var expenseSchema = new Schema({
particular : String,
date : {type : Date, default: Date.now},
paid_by : String,
amount : Number
});
// your schema
var mySchema = new Schema({
name : {type: String, trim: true},
admin : {type: String, trim: true},
expense: [expenseSchema]
});
--- UPDATE:
With this update now expense is an array of expenseSchema without any categorisation of month. Then if you want to get all expenses in a particular month you can simply do an aggregation like this:
db.users.aggregate(
[
// this match is for search the user
{ $match: { name: "<ADMIN NAME>"} },
// this unwind all expenses of the user selected before
{ $unwind: "$expense" },
// this project the month number with the expense
{
$project: {
expense: 1,
month: {$month: '$expense.date'}
}
},
// this search all the expenses in a particular month (of the user selected before)
{ $match: { month: 8 } },
// this is optional, it's for group the result by _id of the user
//(es {_id:.., expenses: [{}, {}, ...]}. Otherwise the result is a list of expense
{
$group: {
_id:"$month",
expenses: { $addToSet: "$expense"}
}
}
]);