Mongoose $gte Date - node.js

Why is mongo client returning an answer for the query and Mongoose is not.
db.dates.find({"date_out" : { $gte : ISODate("2018-11-12T00:00:00.000Z") }}).pretty()
{
"_id" : ObjectId("5be8a9eeda7bbc1fc40c1fa1"),
"user" : "some.user#example.com",
"date_in" : ISODate("2018-11-11T22:15:10.095Z"),
"date_out" : ISODate("2018-11-14T22:00:00Z"),
"userId" : "5be5a96e6db7be0568ea6e47"
}
But when I try to do the same query in Mongoose it doesn't return anything
import Dates from "../models/Date";
import moment from 'moment';
const today = moment().startOf('day').toDate(); // 2018-11-11T22:00:00.000Z
const query = { date_out : { $gte : today }};
router.get("/unavailable", (req, res) => {
Dates.find( query )
.then(Booked_Dates => res.json({ Booked_Dates }))
.catch(err => res.status(400).json({ errors: parseErrors(err.errors) }));
});
Also tried const query = { date_out : { $gte : 'ISODate("${today}")' }};
' = `
Can you please point me in the right direction.
PS: If I take out the query it returns the proper result.
Also this is the schema:
import mongoose from "mongoose";
const schema = new mongoose.Schema({
user: { type: String, required: true },
date_in: { type: String, required: true },
date_out: { type: String, required: true },
userId: { type: mongoose.Schema.Types.ObjectId, required: true }
});
export default mongoose.model("Date", schema);

Related

Ref in mongoose model not giving output

I am using mongoose for defining schema. I have two schemas user and Userdetail. i want data from user in userdetail
I have below schema but i am not getting the output. i think the code is correct but not getting why there is no output...instead i am getting empty array.
const mongoose = require("mongoose")
const UserDetailSchema = mongoose.Schema({
Phone : {
type : Number
},
FirstName : {
type : String
},
LastName : {
type : String
},
productimage : {
data : Buffer,
contentType : String
},
IsDeleted:{
type:Boolean,
default:false
},
UserID : {
type : String,
},
data : [{
type: mongoose.Schema.Types.ObjectId,
ref: "user"
}],
},
{timestamps: true})
const UserDetail = new mongoose.model("userdetail",UserDetailSchema);
module.exports = UserDetail;
my user schema is,
const mongoose = require("mongoose");
const UserSchema = mongoose.Schema({
email: {
type: String,
required: true
},
password: {
type: String,
required: true
},
IsDeleted:{
type:Boolean
},
},
{timestamps: true});
module.exports = mongoose.model("user", UserSchema);
query is,
<pre>
router.get("/UserDetail",async (req,res)=>{
try{
const UsersData= await UserDetail.find();
res.json(UsersData)
}catch(e){
res.status(500).json({ message: e.message })
}
})
</pre>
Even though i am using only find, i must get the data with only id right?
Output is -
Any help would be appreciated
router.patch("/UserDetail/:id",Auth,upload.single("productimage"),async(req,res)=>{
try{
const id = req.params.id;
const updatedData = req.body;
updatedData.productimage = {data: fs.readFileSync('upload/' + req.file.filename),
contentType: 'image/png'};
const options = { new: true };
const result = await UserDetail.findOneAndUpdate(
id, updatedData, options
)
res.send(result)
}catch(e){
res.status(500).json({ message: e.message })
}
})
You can populate a field with the populate function:
const userDetails = await UserDetail.find({}).populate('data').exec();
firstly you need a little change in userID in schema of userDetail.Please make it to UserID:{type : mongoose.Schema.Types.ObjectId}, as it will help you in future during aggregation and you can also remove data from your userDetail model as it will not store any data until you save it.And lastly try to run this aggregation query.
const UsersData= await UserDetails.aggregate([
{$lookup:
{
from: "users",
localField: "userID",
foreignField: "_id",
as: "data"
}
}])
In this way your respective details of users will be displayed in array of data.
Make changes in your model and then populate the data.
const mongoose = require("mongoose")
const UserDetailSchema = mongoose.Schema({
Phone : {
type : Number
},
FirstName : {
type : String
},
LastName : {
type : String
},
productimage : {
data : Buffer,
contentType : String
},
IsDeleted:{
type:Boolean,
default:false
},
UserID : {
type : String,
},
data : {
type: mongoose.Schema.Types.ObjectId,
ref: "user"
},
},
{timestamps: true})
}
populate query
let Model=//import your model here
let userdata=await Model.find().populate("data")
console.log(userdata)

How to delete an object from an array in a mongoose Schema?

User Schema
const UserSchema = new mongoose.Schema({
name : {
type: String,
required : true
},
email : {
type: String,
required : true
},
password : {
type: String,
required : true
},
date : {
type: Date,
default : Date.now,
},
todo : [{ type : mongoose.Schema.Types.Mixed,ref : 'Todo'}]
})
const User = mongoose.model('User',UserSchema);
module.exports = User;
Todo Schema
const TodoSchema = ({
task : String
})
const Todo = mongoose.model('Todo', TodoSchema)
module.exports = Todo;
Database
How do I delete a single todo object i.e("Task 1") from the user?
router.get('/delete/:id',ensureAuthenticated, (req,res)=>{
id = req.params.id
user = req.user
User.update({ }, { "$pull": { task: id }});
tasks = user.todo
res.render("todo/all",{
todo:tasks,
});
})
I have tried all the stackoverflow threads for over 4 hours and I still coudn't figure out what's wrong. Really apprecitate it if you could help it out.
Thank You :)

StrictModeError on using upsert with updateOne in Mongoose

I want to add a list of users in DB if they do not exist in DB and skip for the ones which already exists, for this, I am using writeMany operation with updateOne and upsert set as true. But it gives me StrictModeError.
Here is the function which creates the insertMany
const bulkWriteData = blacklistData.map(value => {
return {
updateOne : {
upsert: true,
filter : {
email : value
},
update : {
$set : {
_id : mongoose.Types.ObjectId(),
status : STATUS.BLOCKED,
createdAt : new Date(),
updatedAt : new Date()
}
}
}
}
})
await EmailUsers.bulkWrite(bulkWriteData)
Here is the EmailUsers Model
const mongoose = require('../config/connection')
const Schema = mongoose.Schema
const validator = require('../utils/validator.util')
const uniqueValidator = require('mongoose-unique-validator')
const EmailUsers = new Schema({
email: {
type: String,
required: true,
validate: validator.mongooseEmailValidator,
unique: true,
},
status: {
type: String,
enum: ['active', 'bounced'],
required: true,
default: 'active',
},
createdAt: {
type: Date,
required: true,
default: () => new Date(),
},
updatedAt: {
type: Date,
required: true,
default: () => new Date(),
},
bounceResponse: [
{
type: Object,
required: false,
},
],
})
EmailUsers.index({ email: 1, status: 1 })
EmailUsers.plugin(uniqueValidator, { type: 'mongoose-unique-validator' })
module.exports = mongoose.model('email_users', EmailUsers)
This is the validator used for email
const mongooseEmailValidator = validate({
validator: 'matches',
arguments: constants.regex.email,
message: 'Email should be a valid email address',
})
Here is the array which was sent to bulkwrite
[{
updateOne : {
upsert : true,
filter : { email: 'test#gmail.com' },
update : {
'$set': {
_id: 607ec7fd009fc824c5c34b5d,
status: 'blocked',
createdAt: 2021-04-20T12:24:29.693Z,
updatedAt: 2021-04-20T12:24:29.693Z
}
}
}
}]
Here is the error
error: Path "email" is not in schema, strict mode is `true`, and upsert is `true`. {"trace":"StrictModeError: Path \"email\" is not in schema, strict mode is `true`, and upsert is `true`.\n at cast
This doesn't make sense as I do have email in the schema
This actually updates the DB with the data and then throws the error.
What could be the possible solution?

Mongoose: Child document does not update on parent document update

I've been on this problem for quite a while. I have 2 schemas:
**The User Schema**
const mongoose = require('mongoose');
const PaymentSchema = require('../models/payments').schema;
const UserSchema = new mongoose.Schema({
firstname :{
type : String,
required : true
} ,
lastname :{
type : String,
required : true
} ,
email :{
type : String,
required : true
} ,
country :{
type : String,
required : true
} ,
state :{
type : String,
required : true
} ,
city :{
type : String,
required : true
} ,
postal :{
type : String,
required : true
} ,
phone :{
type : String,
required : true
} ,
plan :{
type : String,
} ,
amount :{
type : String,
} ,
profit:{
type: String,
},
amountDue:{
type: String,
},
password :{
type : String,
required : true
} ,
withdrawals :[PaymentSchema],
payDate :{
type : Date,
default : Date.now
},
date :{
type : Date,
default : Date.now
}
});
const User= mongoose.model('User', UserSchema);
module.exports = User;
The payments Schema
const mongoose = require('mongoose');
const PaymentSchema = new mongoose.Schema({
firstname: {
type: String
},
lastname:{
type: String
},
balance:{
type: String
},
address: {
type: String,
required: true
},
amount: {
type: Number,
required: true
},
paid: {
type: Boolean,
required: true
},
userid:{
type: String
},
date: {
type: Date,
default: Date.now
}
});
const Payment = mongoose.model('Payment', PaymentSchema);
module.exports = Payment;
The logic is this: When a user makes payment, a POST request is sent and the information from the payment request is displayed on an admin dashboard. The POST request looks like this:
router.post('/users/:id/payments', function (req, res) {
User.findById(req.params.id, function (err, fuser) {
if (err) {
req.flash('error_msg', 'Something went wrong. Please login and try again')
res.redirect('/logout')
} else {
var pay = new Payment({
firstname: fuser.firstname,
lastname: fuser.lastname,
balance: fuser.amount,
amount: req.body.usd,
address: req.body.to,
paid: false,
userid: fuser.id
})
pay.save(function (err, pays) {
if (err) {
console.log(err)
} else {
User.findById(req.params.id, function (err, userr) {
userr.withdrawals.push(pays)
userr.save(function (err, user) {
if (err) {
req.flash('error_msg', 'Something went wrong. Please login and try again')
res.redirect('/logout')
} else {
res.redirect('/dashboard')
}
})
})
}
})
}
})
The information sent to the admin dashboard is then approved and the admin makes a PUT request to that particular payment, updating the "paid" property to "true". Like so:
router.put('/admin/withdrawals/:id', function (req, res) {
var update = {
paid: true
}
Payment.findByIdAndUpdate(req.params.id, update, function (err, user) {
if (err) {
res.send("error!")
} else {
User.findById(user.userid, function (err, uza) {
if (err) {
res.send("error!")
} else {
var amount = uza.amount
var deduct = req.body.aamount
var balance = parseInt(amount) - parseInt(deduct)
var updated = {
amount: balance,
}
User.findByIdAndUpdate(user.userid, updated, function (err, pays) {
if (err) {
res.send(err)
} else {
req.flash('success_msg', 'Withdrawal has been confirmed!')
res.redirect('/admin/dashboard')
}
})
}
})
}
})
})
The payment document gets updated to "true" but the embedded payment document on the User Schema still remains "false".
Please what do I need to do to update the paid property from "false" to "true" on both the main payment document and on the embedded payment document?
You need to link between the schemas like so:
withdrawals: [{ type: Schema.Types.ObjectId, ref: 'Payment' }],
Otherwise you have to update the data in both schemas manually!
See the docs here: https://mongoosejs.com/docs/api.html#schematype_SchemaType-ref

Is it possible to query subdocuments directly using mongoose?

let's say there was a User model and a Post model. In this situation User's would have many posts; User would be the parent and Post would be the child. Is it possible to query for posts directly?
For instance if I wanted to do something like
app.get('/post/search/:query', (req,res) => {
Posts.find({title: req.params.query }, (err,post) => {
res.send(JSON.stringify(post))
})
})
or would one have to do:
app.get('/post/search/:query',(req,res) => {
let resultsFromQuery = [];
User.find({'post.title':req.params.query'}, (err,user) => {
user.posts.forEach((post) => {
if(post.title === req.params.query){
resultsFromQuery.push(post);
}
})
})
res.send(JSON.stringify(resultsFromQuery))
})
EDIT: Here is my schema's.
User Schema (Parent)
const mongoose = require('mongoose'),
Schema = mongoose.Schema,
PostSchema = require('./post.js');
let UserSchema = new Schema({
username: {
type: String,
required: true,
unique: true
},
password: {
type: String,
required: true
},
posts: [PostSchema]
})
module.exports = mongoose.model('User',UserSchema);
Post Schema (Child)
const mongoose = require('mongoose'),
Schema = mongoose.Schema;
let PostSchema = new Schema({
title: {
type: String
},
description: {
type: String
},
image: {
type: String
},
original_poster: {
id: {
type: String,
required: true
},
username: {
type: String,
required: true
}
},
tags: {
type: [String],
required: true
}
})
module.exports = PostSchema;
EDIT:
Here is a sample document
the result of db.users.find({username: 'john'})
{
"_id" : ObjectId("5a163317bf92864245250cf4"),
"username" : "john",
"password" : "$2a$10$mvE.UNgvBZgOURAv28xyA.UdlJi4Zj9IX.OIiOCdp/HC.Cpkuq.ru",
"posts" : [
{
"_id" : ObjectId("5a17c32d54d6ef4987ea275b"),
"title" : "Dogs are cool",
"description" : "I like huskies",
"image" : "https://media1.giphy.com/media/EvRj5lfd8ctUY/giphy.gif",
"original_poster" : {
"id" : "5a163317bf92864245250cf4",
"username" : "john"
},
"tags" : [
"puppies",
"dogs"
]
}
],
"__v" : 1
}
Yes you can find directly the post title from the user model. like bellow
User.find({"posts.title": "Cats are cool"}, (err, users) => {
if(err) {
// return error
}
return res.send(users)
})
That will return user with all post not only the matching post title. So to return only matching post title can use $ positional operator. like this query
User.find({"posts.title": "Cats are cool"},
{username: 1, "posts.$": 1}, // add that you need to project
(err, users) => {
if(err) {
// return error
}
return res.send(users)
})
that only return matching post
Since you are saving OP data, why not do:
// you'll need to adapt how your are getting the user-id here
const { user } = req
Post.find({ title: 'the title', 'original_poster.id': user.id }, (err, posts) => {
console.log(posts); })
Though I would advise you to adjust your Post-schema:
original_poster: {
type: Schema.Types.ObjectId,
ref: 'User'
}
},
Then you can do Post.find({}).populate('original_poster') to include it in your results.!

Resources