MongoDB won't save url string - mongodb

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
},

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

Doubts on Mongodb query

I was designing a classifieds web app with the MERN stack. The MongoSchema is as shown below
const UserSchema = new Schema({
name: {
type: String,
required: true
},
email: {
type: String,
required: true
},
password: {
type: String,
required: true
},
books: [{
title: { type: String },
author: { type: String },
desc: { type: String },
price: { type: String },
image: { data: Buffer, contentType: String }
}],
date: {
type: Date,
default: Date.now
}
});
So all the other info except the books[] will be available after the initial sign-up, but what I want to do is to update the books array every time the user wishes to post a book for selling.
I'm planning to find the user by id, but I'm not quite sure how to add/append the info to the books array.
There are some answers to your question already in Stackoverflow.
For example:
Using Mongoose / MongoDB $addToSet functionality on array of objects
You can do something like this:
UserModel.js
const mongoose = require("mongoose");
const UserSchema = new Schema({
name: {
type: String,
required: true
},
email: {
type: String,
required: true
},
password: {
type: String,
required: true
},
books: [{
title: { type: String },
author: { type: String },
desc: { type: String },
price: { type: String },
image: { data: Buffer, contentType: String }
}],
date: {
type: Date,
default: Date.now
}
});
module.exports = User = mongoose.model("user", userSchema);
After that, in your router file you can try something like this for the books array:
const res = await User.updateOne({ email: 'gintama#bandainamco.com' }, {'$addToSet':{
'books':{
title: "Gintama: The Final",
author: "Sorachi",
desc: "Final Arc",
price: "44.99",
image: "src"
}}); //addToSet if you don't want any duplicates in your array.
OR
const res = await User.updateOne({ email: 'gintama#bandainamco.com' }, {'$push':{
'books':{
title: "Gintama: The Final",
author: "Sorachi",
desc: "Final Arc",
price: "44.99",
image: "src"
}}); //push if duplicates are okay in your array

Push ObjectId to nested array in Mongoose

(Basic library CRUD application)
I am trying to create a document containing some global data about a given book, and then within a User document, add the ObjectId of the newly-created book to an array containing all books belonging to that user.
I have three data models in my application:
var userSchema = new mongoose.Schema({
name: String,
password: String,
email: String,
books: [BookInstanceSchema],
shelves: [String]
});
var bookSchema = new mongoose.Schema({
title: {
type: String,
required: true
},
author: {
type: String,
required: true
},
description: String,
pageCount: Number,
ISBN: String,
googleID: String,
thumbnail: String,
publisher: String,
published: String,
});
var BookInstanceSchema = new mongoose.Schema({
bookId: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Book'
},
userReview: String,
userRating: {
type: Number,
get: v => Math.round(v),
set: v => Math.round(v),
min: 0,
max: 4,
default: 0
},
shelf: String
});
The User model contains a nested array of BookInstances, which contain user-specific data such as ratings or reviews for a given book. A bookInstance in turn contains a reference to the global data for a book, to avoid duplicating data that isn't specific to any user.
What I'm trying to do is first save the global data for a book (thus generating an _id), and when done, save a bookInstance containing that _id in a given user's array of books:
router.post('/save/:id', function(req, res) {
var url = encodeurl('https://www.googleapis.com/books/v1/volumes/' + req.params.id);
request(url, function(err, response, data) {
parsedData = JSON.parse(data);
var newBook = {
title: parsedData.volumeInfo.title,
author: parsedData.volumeInfo.authors[0],
description: parsedData.volumeInfo.description,
pageCount: parsedData.volumeInfo.pageCount,
ISBN: parsedData.volumeInfo.description,
googleID: parsedData.id,
publisher: parsedData.volumeInfo.publisher,
published: parsedData.volumeInfo.publishedDate,
thumbnail: parsedData.volumeInfo.imageLinks.thumbnail
};
Book.create(newBook, function(err, newBook) {
if (err) {
console.log(err);
}
else {
console.log(newBook._id);
console.log(mongoose.Types.ObjectId.isValid(newbook._id));
User.findByIdAndUpdate(req.session.id, {
$push: {
"books": {
bookId: newBook._id,
userRating: 0,
userReview: ''
}
}
},
{
upsert: true
},
function(err, data){
if(err) {
console.log(err);
}
else {
res.redirect('/');
}
});
}
});
});
});
I'm getting the error:
message: 'Cast to ObjectId failed for value "hjhHy8TcIQ6lOjHRJZ12LPU1B0AySrS0" at path "_id" for model "User"',
name: 'CastError',
stringValue: '"hjhHy8TcIQ6lOjHRJZ12LPU1B0AySrS0"',
kind: 'ObjectId',
value: 'hjhHy8TcIQ6lOjHRJZ12LPU1B0AySrS0',
path: '_id',
reason: undefined,
Every time, the value in the error (in this case, jhHy8T...) is different than the newBook._id I'm attempting to push into the array:
console.log(newBook._id); // 5a120272d4201d4399e465f5
console.log(mongoose.Types.ObjectId.isValid(newBook._id)); // true
It seems to me something is wrong with my User update statement:
User.findByIdAndUpdate(req.session.id, {
$push: {
"books": {
bookId: newBook._id,
userRating: 0,
userReview: ''
}
}...
Any help or suggestions on how to better organize my data are appreciated. Thanks!

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