Mongoose save image using JWT token ID update field under ID - mongodb

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

Related

MongoDB won't save url string

I am trying to save an object in my Mongo database. The issue I face is that when I create the schema, it saves every single entry except the img url. I logged the url before creating the schema and it prints it successfully but when I create the schema object it doesn't get the value from the body.
router.post('/', async (req, res) => {
console.log("URL:", req.body.img) //Logs the url successfully
const pet = new Pet({
name: req.body.name,
petType: req.body.petType,
breed: req.body.breed,
age: req.body.age,
img: req.body.img, //i can't get it here
contact: req.body.contact,
location: req.body.location,
userp: req.body.contact,
})
console.log("This is a Pet");
console.log(pet); //logs everything except the "img" field.
try {
const savedPet = await pet.save();
console.log("This pet was saved", savedPet);
res.json(savedPet); //returns an object without the "img" field
} catch (err) {
res.json({ message: err });
}
});
Edit:
Here is my schema file as well:
const mongoose = require('mongoose');
const petSchema = mongoose.Schema({
name: {
type: String,
required: false
},
petType: {
type: String,
require: true
},
breed: {
type: String,
require: false
},
age: {
type: Number,
require: false
},
img: {
data: String,
require: false
},
contact: {
type: String,
require: true
},
location: {
type: String,
require: true
},
userp: {
type: String,
require: true
}
});
module.exports = mongoose.model('Pet', petSchema);```
I found the error. You use data instead type param specifically in this property.
img: {
type: String,
require: false
},

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')
}
})

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

MongoDB - Update Array with different types (discriminatorKey)

I have a document which can have an array of different sub documents.
Saving documents to the database work fine and the structure is exactly what I need.
My Problem is that I can not update values in the "sections" array (schema below)
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const logoSchema = require('./site-sections/logo');
var sectionSchema = new Schema(
{
show: { type: Boolean, default: true },
order: Number
},
{ discriminatorKey: 'type' }
);
const siteSchema = new Schema({
_user: { type: Schema.Types.ObjectId, ref: 'User' },
type: { type: String, required: true },
title: { type: String, default: '' },
name: { type: String, required: true },
password: { type: String, default: '' },
caching: { type: Number, default: 1 },
unique_id: { type: String, required: true },
sections: [sectionSchema]
});
const sectionArray = siteSchema.path('sections');
const headerSchema = new Schema({
image: { type: String, default: '' },
title: { type: String, default: '' },
sub_title: { type: String, default: '' },
show: { type: Boolean, default: true },
logo: logoSchema
});
sectionArray.discriminator('header', headerSchema);
const textSchema = new Schema({
text: String
});
sectionArray.discriminator('text', textSchema);
module.exports = mongoose.model('site', siteSchema);
My Update function:
req.body has the following value:
{ key: 'title',
value: 'Test',
unique_site_id: '_jxn7vw' }
const Site = require('../../models/site');
exports.update = async function(req, res, next) {
console.log(req.body);
if (req.body.unique_site_id) {
Site.update(
{
unique_id: req.body.unique_site_id,
_user: req.user.id,
'sections.type': 'header'
},
{
$set: {
['sections.$.' + req.body.key]: req.body.value
}
},
function(err, status) {
if (err) {
console.log(err);
return res.status(500).send();
}
console.log(status);
return res.status(200).send();
}
);
}
};
The console.log(status) always prints: { ok: 0, n: 0, nModified: 0 }.
How can I update the title value?
Discriminator keys cannot be updated. https://github.com/Automattic/mongoose/issues/3839
Ok. So the right order is:
convert mongoose document to object with toObject()
change discriminator, and change/delete other properties
convert back to mongoose document with hydrate()
save