Filter array with Model.find() Mongoose - node.js

I have a mongoose model where one of the fields is an array of dates and I need to query the collection to find any document that has a date between the 7 past days inside that array, but when I try to use $gt or $gte it doesn't return me the documents, even if exists (I have checked if the documents exist).
Here it is an example of the object
It shouldn't return me objects with more than 7 days past.
Here is the code that I'm using:
const { subDays } = require("date-fns");
const mongoose = require("mongoose");
const Journey = require("./models/Journey");
const url = "my-db-url";
mongoose.set("useNewUrlParser", true);
mongoose.set("useUnifiedTopology", true);
mongoose.set("useCreateIndex", true);
mongoose.set("useFindAndModify", false);
mongoose.connect(url, (err) => {
if (err) throw err;
console.log("Mongoose connected");
});
Journey.find({
hospital: "5e6fc0d98db5810012aeb8fe",
active: false,
timestampStart: {
$gte: subDays(new Date(), 7)
}
})
.lean()
.exec((err, journeys) => {
if (err) throw err;
console.log(journeys[0]);
});
The Journey model:
const { Schema, model } = require("mongoose");
const JourneySchema = new Schema(
{
tag: {
type: Schema.Types.ObjectId,
required: true,
ref: "Tag",
},
patient: {
type: Schema.Types.ObjectId,
required: true,
ref: "Patient",
},
hospital: {
type: Schema.Types.ObjectId,
required: true,
ref: "Hospital",
},
department: {
type: [String],
required: true,
},
timestampStart: {
type: [Date],
required: true,
},
timestampEnd: {
type: [Date],
required: true,
},
active: {
type: Boolean,
default: true,
},
rssi: {
type: [String],
required: true,
},
},
{
timestamps: true,
}
);
module.exports = model("Journey", JourneySchema);
Can anyone help me build this filter?

The date query seems to working just fine. I think the problem would be with the hospital, and active key. In the sample object that you have provided, both are missing. Can you check it by removing those keys in the query, or by adding them in the collection.

Related

How to populate the nested objects in mongoose?

here's the booking schema
const bookingSchema = new mongoose.Schema({
userId: {
type: mongoose.Schema.Types.ObjectId,
ref: "User",
required: true,
},
routeId:{
type: mongoose.Schema.Types.ObjectId,
ref: "Route",
required: true,
}
})
In this table the routeId(route schema) contains the Bus table(referenced).
const routeSchema = new mongoose.Schema({
location:{
type: mongoose.Schema.Types.ObjectId,
ref: 'Location',
required: true
},
duration: {
type: Number,
required: true
},
Bus:{
type: mongoose.Schema.Types.ObjectId,
ref:"Bus",
required: true
},
date: {
type:String,
required: true
},
},
{
timestamps: true,
});
and then finally the bus model
const busSchema = new mongoose.Schema(
{
busNumber: {
type: String,
unique: true,
required: true,
},
seats: {
type: Number,
},
},
{
timestamps: true,
}
);
Now I want to show only bus number and not whole bus data. this is the response I am getting. https://i.stack.imgur.com/S1qyZ.png
this is the query that I applied.
router.get("/bus/myBooking/one/:id", auth, async (req, res) => {
const _id = req.params.id;
const myBooking = await Booking.findById({ _id })
.populate({path: 'routeId', populate: 'Bus'})
.select(["-_id","-userId","-createdAt","-updatedAt","-__v","-passengers._id","-departureDetails._id","-arrivalDetails._id"]);
try {
return !myBooking
? res.status(404).send("No booking found")
: res.status(200).send(myBooking);
} catch (e) {
res.status(500).send();
}
});
This method works on some versions of mongoose, So you can try this:
await Booking.findById({ _id })
.populate({
path: 'routeId',
populate: {
path: 'Bus',
model: Bus,
select:"-_id busNumber"
}
})

populate an array in mongodb

i have 2 schemas
const schema = mongoose.Schema(
{
id_film: {
type: Number,
unique: true,
require: true,
trim: true,
},
recommendation: [{
type: Number,
ref: 'Films'
}]
}, { timestamps: true }, { _id: false }
);
export const Recommendation = mongoose.model("Recommendations", schema);
const schema = mongoose.Schema(
{
name:{
type: String,
}
id: {
type: Number,
ref: 'Recommendations'
},
}
export const Films = mongoose.model("Films", schema);
the recommendation contains a list id of model Films, and I want to show all id film
i try it
Recommendation.findOne({ id_film: req.params.id }).populate('recommendation').exec(function (err, film) {
if (err) return handleError(err);
res.json(film);
});
but it's not working, it just shows the list id not id and name

MissingSchemaError: Schema hasn't been registered for model during populate

I have two models
1.PageType Model
module.exports = (mongoose) => {
const pageTypeSchema = new mongoose.Schema({
title: {
type: String,
key: {
type: String,
required: true,
},
}, {
timestamps: { createdAt: 'created_at', updatedAt: 'updated_at' },
});
return mongoose.model('PageType', pageTypeSchema);
};
WorkFlow Model
module.exports = (mongoose) => {
const workFlowSchema = new mongoose.Schema({
title: {
type: String,
default: null,
},
key: {
type: String,
default: null,
},
level: {
type: Number,
required: true,
},
page_type_id: {
type: mongoose.Schema.Types.ObjectId,
ref: 'PageType',
},
}, {
timestamps: { createdAt: 'created_at', updatedAt: 'updated_at' },
});
return mongoose.model('WorkFlow', workFlowSchema);
};
But when I try to use populate it throws Schema hasn't been registered for model PageType
async getFlowById(flowId) {
const result = await this.workFlow.findById(flowId).populate('page_type_id').exec();
return result;
}
Can anyone please help me with this??
In app.js the models are included before routes also PageType model is also declared before WorkFlow model
You typed wrong collection name. Collection name is Workflow and you are trying to findById at workflow. So i think Workflow should be there. Just try with that.

Referencing Object Id not working in Mongoose 4.11.6

I have this problem. Basically, I have 2 schemas - a User schema and a Document schema. The Document schema has an owner which references the _id field of documents in the User collection.
The problem is that I am still able to save documents in the Document collection with owner ids that do not exist in the User collection which should not be so.
Here is my User schema and Document schema respectively
const UserSchema = new Schema({
firstName: {
type: String,
required: true,
},
lastName: {
type: String,
required: true,
},
email: {
type: String,
validate: [{ validator: value => isEmail(value), msg: 'Invalid email.'
}],
unique: true,
required: true,
},
password: {
type: String,
required: true,
},
isAdmin: {
type: Boolean,
default: false,
},
}, {
timestamps: true,
});
const User = mongoose.model('User', UserSchema);
And the Document Schema
const DocumentSchema = new Schema({
title: {
type: String,
required: true,
},
text: {
type: String,
},
access: {
type: String,
enum: ['public', 'private'],
default: 'public',
},
owner: {
type: Schema.Types.ObjectId,
ref: 'User',
required: true,
},
}, {
timestamps: true,
});
const Document = mongoose.model('Document', DocumentSchema);
Any help will be appreciated thanks.
For that situation you can add pre save function in your Document schema that will call before save your Document.
const DocumentSchema = new Schema({
// ...
}, {
timestamps: true,
});
DocumentSchema .pre("save",function(next) {
var self = this;
if (self.owner) {
mongoose.models['User'].findOne({_id : self.owner }, function(err, existUser){
if(err){
return next(false, err);
}
if(!existUser)
return next(false, "Invalid user reference");
else
return next(true);
});
} else {
next(false, "Owner is required");
}
});
const Document = mongoose.model('Document', DocumentSchema);

Mongoose Virtual field with async getter

I have a item model where it a virtual field to refer stock badges.
'use strict';
const mongoose = require('mongoose');
const mongooseHidden = require('mongoose-hidden')();
const Badge = mongoose.model('Badge');
const validateProperty = function(property) {
return (property.length);
};
const Schema = mongoose.Schema;
const ItemSchema = new Schema({
itemCode: {
type: Number,
index: {
unique: true,
sparse: true // For this to work on a previously indexed field, the index must be dropped & the application restarted.
},
required: true
},
itemName: {
type: String,
uppercase: true,
trim: true
},
barcode: {
type: String,
trim: true
},
category: {
type: Schema.Types.ObjectId,
ref: 'Category'
},
subCategory: {
type: Schema.Types.ObjectId,
ref: 'SubCategory'
},
updated: {
type: Date
},
created: {
type: Date,
default: Date.now
},
status: {
type: String,
enum: [
'active', 'inactive', 'removed'
],
default: 'active'
}
}, {id: false});
ItemSchema.virtual('badges').get(function() {
return this.getAvailableBadges();
});
ItemSchema.methods.getAvailableBadges = function() {
Badge.find({
item: this._id
}, (err, badges) => {
if (badges) {
return badges;
} else {
return [];
}
});
};
ItemSchema.set('toJSON', {virtuals: true});
ItemSchema.set('toObject', {virtuals: true});
ItemSchema.plugin(mongooseHidden, {
hidden: {
_id: false,
__v: true
}
});
mongoose.model('Item', ItemSchema);
And batch model as below
'use strict';
const mongoose = require('mongoose');
const mongooseHidden = require('mongoose-hidden')();
const validateProperty = function(property) {
return (property.length);
};
const Schema = mongoose.Schema;
const BadgeSchema = new Schema({
item: {
type: Schema.Types.ObjectId,
ref: 'Item'
},
qty: {
type: Number,
validate: [validateProperty, 'Please enter Quantity !']
},
purchasingPrice: {
type: Number,
validate: [validateProperty, 'Please enter purchasingPrice !']
},
sellingPrice: {
type: Number,
validate: [validateProperty, 'Please enter sellingPrice !']
},
updated: {
type: Date
},
created: {
type: Date,
default: Date.now
},
status: {
type: String,
enum: [
'active', 'inactive', 'removed'
],
default: 'active'
}
});
BadgeSchema.plugin(mongooseHidden, {
hidden: {
_id: false,
__v: true
}
});
mongoose.model('Badge', BadgeSchema);
Item's badge virtual field doesn't got populated.
How are we going to work with async getter method
I have put some console log statements and found that getAvailableBadges is getting data.
I need to send json object with virtual field values via express. How to I do it?
What I did was create an virtual property
ItemSchema.virtual('badges', {
ref: 'Badge',
localField: '_id',
foreignField: 'item'
});
And populate it with
{
path: 'badges',
select: [
'qty', 'purchasingPrice', 'sellingPrice'
],
options: {
sort: {
'created': -1
}
}
}
Well, the operations are asynchronous so you have to wait for the callback to fire.
You can only return the values by passing it in the callback (or you can set the values of the current object prior to calling the callback).
I think it would be something like this:
ItemSchema.virtual('badges').get(function (callback) {
Badge.find({ item: this._id }, callback);
};
Then you would use it like
item.badges(function (err, badges) {
// do something with badges
});

Resources