How can I refer to the schema I was trying to save in nestjs/mongoose? - mongodb

I am trying to encrypt some passwords and get its salt before saving my model to mongoose in Nestjs, but simply using this to refer to the schema itself doesn't yield any results as it refers to the UserSchemaProvider object itself, instead of the current model I'm trying to save.
My schema provider:
export const UserSchemaProvider = {
name: 'User',
useFactory: (): mongoose.Model<User> => {
const UserSchema = new mongoose.Schema({
name: { type: String, required: true },
email: { type: String, required: true, unique: true },
password: { type: String, required: true },
birthday: { type: Date, required: true },
celphoneNumber: String,
whatsapp: Boolean,
promo: Object,
status: String
});
UserSchema.pre<User>('save', async (next) => {
const user = this;
console.log(user);
if (user.password) {
const salt = await bcrypt.genSalt();
bcrypt.hash(user.password, salt, (err, hash) => {
if (err) return next(err);
user.password = hash;
next();
});
}
});
return UserSchema;
},
};
and my user Module comes below:
#Module({
imports: [
MongooseModule.forFeatureAsync([
UserSchemaProvider]),
HttpModule
],
controllers: [UsersController],
providers: [UsersService, Validator, ValidationPipe, IsEmailInUseConstraint, GoogleRecaptchaV3Constraint],
})
:Nest Platform Information:
platform-express version: 6.10.14
mongoose version: 6.3.1
common version: 6.10.14
core version: 6.10.14

Your pre hook handler shouldn't be an arrow function () => {}. mongoose handler will need to have the execution context to point to a current document being saved. When using arrow function, your execution context of the pre hook is no longer the document, hence, this inside of the handler isn't the document itself anymore.
export const UserSchemaProvider = {
name: 'User',
useFactory: (): mongoose.Model<User> => {
const UserSchema = new mongoose.Schema({
name: { type: String, required: true },
email: { type: String, required: true, unique: true },
password: { type: String, required: true },
birthday: { type: Date, required: true },
celphoneNumber: String,
whatsapp: Boolean,
promo: Object,
status: String
});
UserSchema.pre<User>('save', async function(next) { // <-- change to a function instead
const user = this;
console.log(user);
if (user.password) {
const salt = await bcrypt.genSalt();
bcrypt.hash(user.password, salt, (err, hash) => {
if (err) return next(err);
user.password = hash;
next();
});
}
});
return UserSchema;
},
};

Related

Moongose returns an empty array when using the .find() method, why?

I have a database in MongoDB with some data, I try to get them with the .find() method, but it returns an empty array instead of the array with the data. Why does this happen and how do I fix it? I'm using ES6
Controller:
import {Game} from '../models/Game.js';
export const getAll = async (req, res) => {
try {
let games = await Game.find();
console.log(games) //returns = []
res.status(200).json(games);
} catch(error) {
console.log('Hubo un error', error)
}
};
Model:
import mongoose from "mongoose";
const { Schema, model } = mongoose;
const GameSchema = new Schema({
name: {
type: String,
required: true
},
price: {
type: Number,
required: true
},
description: {
type: String,
required: true
},
genre: {
type: String,
required: true
},
cover: {
type: String,
required: true
},
platform: {
type: String,
required: true
},
});
export const Game = model("Game", GameSchema);

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

Populate data using another collection in mongoose v6.2.8

Im having issues populating my mongoDB collection with another collection based off the _id. It Keeps returning an empty object with no errors or anything?
Property Schema
const PropertySchema = new Schema({
landlord: {
type: Schema.Types.ObjectId,
ref: "Landlord",
required: true,
},
...
});
Landlord Schema
import { Schema as _Schema, model } from "mongoose";
const Schema = _Schema;
const LandlordSchema = new Schema({
fname: {
type: String,
required: true,
},
lname: {
type: String,
required: true,
},
phone: {
type: Number,
required: true,
},
email: {
type: String,
required: true,
},
company: {
type: String,
},
});
const Landlord = (module.exports = model("Landlord", LandlordSchema));
export function get(callback, limit) {
Landlord.find(callback).limit(limit);
}
Property Controller
exports.readProperty = async (req, res) => {
await Property.find({ _id: req.params.propertyId })
.populate({
path: "Landlord",
select: "fname lname email phone company",
model: "Landlord",
strictPopulate: false,
})
.then(function (err, property) {
if (err) return res.send(err);
res.json(property);
});
};
mongodb Property Collection
Mongodb Landlord Collection
When running the get call from postman it returns:
I fixed this issue by selecting the field: landlord not Landlord

Schema hasn't been registered for model :mongoose

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);

User is not a constructor

im getting error: User is not a constructor when trying to add new document to my database. before I used mongoose.model without the Schema method and it worked great but I had to add validator and it needs this syntax and since then I can't make it work
CODE:
var UserSchema = mongoose.Schema({
username: { type: String, required: true, unique: true },
email: { type: String, index: true, unique: true, required: true },
password: { type: String, required: true }
});
UserSchema.plugin(uniqueValidator);
let User = mongoose.model("user", UserSchema);
module.exports = User;
router.post('/', (req, res) => {
var user = new User({
username: req.body.username,
email: req.body.email,
password: req.body.password
});
// save the user
user.save(function (err) {
if (err) {
console.log('Error in Saving user: ' + err);
throw err;
}
console.log('User Registration succesful');
// return done(null, userData);
res.status(200).send({user: user})
});
});
mongoose.Schema is a constructor, so you need to call it with "new":
var UserSchema = new mongoose.Schema({
username: { type: String, required: true, unique: true },
email: { type: String, index: true, unique: true, required: true },
password: { type: String, required: true }
});
ok I fixed my issue instead of
module.exports = User;
I had to do:
module.exports = {User};