Schema hasn't been registered for model :mongoose - mongodb

I have a model like this
const Schema = mongoose.Schema
const fileSchema = mongoose.Schema({
ownerId: { type: Schema.Types.ObjectId },
fileTypeId: { type: Schema.Types.ObjectId },
name: { type: String },
data: { type: Schema.Types.Mixed },
fileSize: { type: Number },
isHashInBlockchain: { type: Boolean },
createdAt: { type: Date, default: Date.now },
updatedAt: { type: Date, default: Date.now }
})
fileSchema.virtual('file', {
ref: 'filetype',
localField: 'fileTypeId',
foreignField: '_id'
})
fileSchema.set('toObject', { virtuals: true })
fileSchema.set('toJSON', { virtuals: true })
module.exports = mongoose.model('useruploadedfiles', fileSchema)
I am referring filetype collection to this model
But when I run the following query
await File.find(query).populate({ path: 'file' }).select('_id name createdAt updatedAt').sort({ createdAt: -1 }).skip(limit * (pageNumber - 1)).limit(limit)
I am getting the following error
Schema hasn't been registered for model "filetype"

You have to import your model in your root app file.
model.js
const UserSchema = new mongoose.Schema({
email: {
type: String,
unique: true,
trim: true,
},
name: {
type: String,
required: "Please supply a name",
trim: true
},
});
module.exports = mongoose.model("User", UserSchema);
app.js
mongoose.connect(process.env.DATABASE);
mongoose.Promise = global.Promise; // Tell Mongoose to use ES6 promises
mongoose.connection.on('error', (err) => {
console.error(`🙅 🚫 🙅 🚫 🙅 🚫 🙅 🚫 → ${err.message}`);
});
// READY?! Let's go!
require('./models/User')
router.js
const User = mongoose.model("User");
const getUsers = async (req, res) => res.json(await User.find({}));
app.get('/users', getUsers);

Related

Mongoose delete nested object on time expiration

I'm trying to find out the way to remove nested object in one collection once the document from another collection is expired
LocationsSchema.js
const mongoose = require('mongoose');
const locationsSchema = mongoose.Schema({
name: {
type: String,
required: [true, 'Please add a location name (string)']
},
confirmedBookings: [
{
startDate: {
type: Number
},
finishDate: {
type: Number
}
}]
}, {
timestamps: true
})
module.exports = mongoose.model('Locations', locationsSchema)
BookingsSchema.js
const mongoose = require('mongoose');
const Location = require('./locationModel');
const bookingSchema = mongoose.Schema({
startDate: {
type: Number,
required: [true, 'Please add a valid Date']
},
finishDate: {
type: Number,
> timestamp
required: [true, 'Please add a valid Date'],
index: true
},
location: {
type: mongoose.Schema.Types.ObjectId,
ref: Location
}
}, {
timestamps: true
})
bookingSchema.index({finishDate: 1}, {expireAfterSeconds: 0})
module.exports = mongoose.model('Booking', bookingSchema)
This is how I delete the object manually in
BookingsController.js
const deleteBookings = asyncHandler(async (req, res) => {
const booking = await Booking.findById(req.params.id);
if (!booking) {
res.status(400);
throw new Error('Booking not found');
}
await Location.findOneAndUpdate({_id: booking.location},
{$pull: {'confirmedBookings': {_id: req.params.id}}});
await booking.remove();
res.status(200).json({id: req.params.id});
})
But I also want to be able to delete the objects ones theirs finishDate are before the present time.
I tried to create an TTL index for that but it seems it doesn't work in the way I did it

Mongoose save image using JWT token ID update field under ID

I am trying to save an image filename to an existing user by using a JWT token return of userID. However, it isn't saving the image and I am not exactly sure what I am doing wrong since there is no error output. I am using two schemas one of them is a collection schema and the user schema. The userID is the primary key for the collection schema like this:
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const collections = require('../models/collections')
// Create User Schema
const UserSchema = new Schema({
username: {
type: String,
required: false,
default: null
},
name: {
type: String,
required: true
},
userbio: {
type: String,
required: false,
default: null
},
email: {
type: String,
required: true
},
password: {
type: String,
required: true
},
profileimg: {
type: String,
required: false,
default: null
},
useralert: {
type: String,
required: false,
default: null
},
socials: {
type: String,
required: false,
default: null
},
collections: {
type: Schema.Types.ObjectId,
ref: 'imgCollections' //export ref module.exports = User = mongoose.model("imgCollections", collections);
},
date: {
type: Date,
default: Date.now
}
});
module.exports = User = mongoose.model("users", UserSchema);
here is the collection schema:
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const {ObjectId} = mongoose.Schema.Types;
//imgName, tags, description, cName, date(auto)
// Create Schema
const collections = new Schema({
imgName: {
type: String,
required: true
},
image:{
data: Buffer,
contentType: String
},
tags: {
type: String,
required: true
},
description: {
type: String,
required: true,
default: " "
},
flaggedImage:{
type: Boolean,
required: false,
default: false
},
cName: {
type: String,
required: false,
default: null
},
postedBy: {
type: ObjectId,
ref: "users",
required: true
},
date: {
type: Date,
default: Date.now
}
});
module.exports = User = mongoose.model("imgCollections", collections);
and here is how I am saving my image:
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, "uploads");
},
filename: function (req, file, cb) {
cb(
null,
file.fieldname + "-" + Date.now() + path.extname(file.originalname)
);
},
});
const upload = multer({
storage: storage,
fileFilter: (req, file, cb) => {
if (file.mimetype == "image/png" || file.mimetype == "image/jpg" || file.mimetype == "image/jpeg") {
cb(null, true);
} else {
cb(null, false);
return cb(new Error('Only .png, .jpg and .jpeg format allowed!'));
}
} });
router.post("/collections", requireLogin, upload.single("myImage"), async (req, res) => {
const obj = {
img: {
data: req.file.filename,
contentType: req.file.contentType
}
}
const newCollection = new collections({
imgName: req.file.filename,
image: obj.img
});
const file = req.file
console.log(file)
// apply filter
// resize
/*
//AWS image upload here commented out to prevent duplicate sends
const result = await uploadFile(file)
await unlinkFile(file.path)
console.log(result)
const description = req.body.description
res.send({imagePath: `/images/${result.Key}`})
*/
//mongodb upload
try {
const user = await User.findById(req.user)
user.save(newCollection)
console.log(user)
} catch (error) {
res.status(400).json('updateError: ' + error)
}
any help is appreciated. Also the return for the authentication requireLogin gives back req.user -> id. That works. I am just not sure how to save it under the userID

MongoDB: Find items with the user id

I have a product collection and a user collection where I reference user to my product collection.
So far what I am trying to achieve here is to get only the products that are created by that user.
const getOwnerProduct = expressAsyncHandler(async (req, res) => {
const activeUser = await User.findById(req.user._id)
const pageSize = 10
const page = Number(req.query.pageNumber) || 1
const items = { user: { _id: activeUser } }
const count = await Product.countDocuments({ ...items } )
const products = await Product.find({ ...items }).limit(pageSize).skip(pageSize * (page - 1))
res.json({ products, page, pages: Math.ceil(count / pageSize) })
})
Here's the Product Schema:
const productSchema = mongoose.Schema({
user: {
type: mongoose.Schema.Types.ObjectId,
required: true,
ref: 'User'
},
name: {
type: String,
required: true
},
price: {
type: Number,
required: true,
},
description: {
type: String,
required: true
},
email: {
type: String
},
rating: {
type: Number,
required: true,
default: 0
},
image: {
type: String,
required: true,
default: 0
},
}, { timestamps: true
})
And here's the userSchema:
const userSchema = mongoose.Schema({
name: {
type: String,
required: true
},
email: {
type: String,
required: true,
unique: true
},
phone: {
type: String,
required: true,
unique: true
},
password: {
type: String,
required: true
},
role: {
type: String,
enum: ['administrator', 'productOwner', 'regular'],
default: 'regular'
}
}, { timestamps: true
})
Here's the router:
app.use('/api/products', productRoutes)
router.route('/').get(getProducts, admin).get(getOwnerProducts, productOwner)
For some reason this doesn't work. I think my query on mongodb is not correct.
Any idea what am I missing here?
Here instead of const products = await Product.find({ ...items }) you can try
await User.findById(req.user._id).forEach(element =>{Product.find({user=element._id})});
or
await User.findById(req.user._id).forEach(element =>{Product.find(user=element._id)});

Mongoose 'populate()' not populating

So Im building a simple application with the MEARN stack.
The problem is that i want to have the user's information (name,email, etc...) to be put in the 'user' property in the product , and it's not working (Postman request return 500 status Server error) , i don't know what i'm doing wrong , thanks in advance! my code snippets :
My User Model :
const mongoose = require('mongoose')
const UserSchema = mongoose.Schema({
name : {
type: String,
required: true
},
email : {
type: String,
required: true,
unique: true
},
password : {
type: String,
required: true
},
date : {
type: Date,
default: Date.now
},
})
module.exports = mongoose.model('user',UserSchema)
my Product Model :
const mongoose = require('mongoose')
const ProductSchema = mongoose.Schema({
user:{
type: mongoose.Schema.Types.ObjectId,
ref: 'users'
},
name : {
type: String,
required: true
},
description : {
type: String,
required: true
},
quantity : {
type: Number,
required: true
},
price : {
type: Number,
required: true
},
date : {
type: Date,
default: Date.now
},
})
module.exports = mongoose.model('product',ProductSchema)
and my request :
router.get('/:id', async (req,res) => {
try {
const product = await Product.findById(req.params.id).populate('user')
res.json(product)
} catch (err) {
res.status(500).send('Server Error')
}
})
Your ref value needs to match the name of the model user references. So you need to change it to:
user:{
type: mongoose.Schema.Types.ObjectId,
ref: 'user'
},
You have to specify the path:populate({path:'user'}) Try :
router.get('/:id', async (req,res) => {
try {
const product = await Product.findById(req.params.id).populate({path:'user'})
res.json(product)
} catch (err) {
res.status(500).send('Server Error')
}
})

How to do inner reference with mongoose?

I want to do something like following code, but it failed.
var User = new Schema({
name: { type: String, required: true },
phone_number: { type: String, required: true },
modified: { type: Date, default: Date.now },
contacts: [{
user: { type : Schema.ObjectId, ref : 'User' }
}]
});
var UserModel = mongoose.model('User', User);
Is it able to achieve that purpose?
I think I used the wrong way to check it, actually it works.
Following is my test :
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
mongoose.connect('localhost', 'contacts_test');
var User = new Schema({
name: { type: String, required: true },
phone_number: { type: String, required: true },
modified: { type: Date, default: Date.now },
contacts: [
{
user: { type: Schema.ObjectId, ref: 'User' }
}
]
});
var UserModel = mongoose.model('User', User);
mongoose.connection.on('open', function () {
var user1 = new UserModel({name: 'kos', phone_number: "003"});
user1.save(function (err) {
if (err) throw err;
var user2 = new UserModel({name: 'java', phone_number: "008"});
user2.contacts = [{user: user1._id}];
user2.save(function (err) {
UserModel.findById(user2._id)
.populate('contacts.user')
.exec(function (err, user) {
if (err) console.error(err.stack || err);
console.log('user name: ' + user.name);
console.error('contact of first result : ', user.contacts[0].user.name);
mongoose.connection.db.dropDatabase(function () {
mongoose.connection.close();
});
});
});
});
});