required mongoose validator not working for insertMany? - mongodb

Model schema:
let mySchema = new mongoose.Schema({
area: {
type: String,
required: true
},
dateUpdated: {
type: Date,
required: true
},
data: {
type: Object,
required: true
},
fileName: {
type: String,
required: true
},
datetimeCreated: {
type: Date,
default: new Date()
},
dateTimeDeleted: {
type: Date
}
}, {
collection: 'my_collection'
});
Sample data to insert:
[{
area: 'Some Area',
// I'm forcing it to be undefined if the data was not provided in attempt to fix the problem,
// but it just gets stored as null
dateUpdated: undefined,
data: {
key1: 1,
key2: 2
},
fileName: 'sample-file.xlsx',
datetimeCreated: 2021-03-03T09:10:51.966Z,
}
];
Insert:
let myModel = new MyModel();
return new Promise((resolve, reject) => {
myModel.collection.insertMany(sortedData, (err) => { ... } });
The process is that you upload an Excel file and there's a column for dateUpdated but if the user left that blank it should return an error when they try to upload the file.
What happens right now is the whole thing still gets uploaded, with dateUpdated just set to null.

Honest mistake.
Instead of using:
let myModel = new MyModel();
return new Promise((resolve, reject) => {
myModel.collection.insertMany(sortedData, (err) => { ... } });
I had to do:
// Not needed --> let myModel = new MyModel();
return new Promise((resolve, reject) => {
// Remove .collection
myModel.insertMany(sortedData, (err) => { ... } });

Related

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

How to update a user profile which has a property which is a ref in MongooseJS?

I have a User schema which has reference to a profile schema.
const UserSchema = new Schema(
{
_id: mongoose.Schema.Types.ObjectId,
email: {
....email props...
},
password: {
...password props...
},
profile: [{
type: mongoose.Schema.Types.ObjectId,
ref: "Profile",
}],
},
);
const Profile = new Schema({
_user: {
type: Schema.Types.ObjectId, ref: 'User'
},
'displayName': {
type: String,
default: ''
},
'interestedActivities': ['Ping-pong'], <---- This bad boy/girl is an array
'memberSince': { type: Date, default: Date.now }
}
)
I'd like to create a route which can update the User properties AND the Profile properties in one shot—with a caveat one of the properties on the Profile model is an array!!!
I tried this....
handler
.use(auth)
.put((req, res, next) => {
emailValidator(req, res, next, 'email');
},
async (req, res, next) => {
await connectDB()
const {
profileDisplayName,
profileEmail,
interestedActivities } = req.body;
const update = {
email: profileEmail,
'profile.$.displayName': profileDisplayName,
'profile.$.interestedActivities': interestedActivities
}
const filter = { _id: req.user.id };
const updatedUser = await User.findOneAndUpdate(filter, update, { new: true })
try {
console.log("updatedUser ", updatedUser);
if (updatedUser) {
return res.status(200).send({
updatedUser,
msg: `You have updated your profile, good job!`
});
}
} catch (error) {
errorHandler(error, res)
}
})
export default handler;
My response is:
Status Code: 500 Internal Server Error
Cast to ObjectId failed for value "[
{
id: 'ae925393-0935-45da-93cb-7db509aedf20',
name: 'interestedActivities',
value: []
}
]" (type Array) at path "profile.$"
Does anyone know how I could also afford for the property which is an array?
Thank you in advance!

graphql query return object with null id

Graphql return Oject with null id.
with mongodb.
It looks strange to me.
If I delete new GraphQLNonNull() on MailType id,
It works with id: null, another fields working fine.
const MailType = new GraphQLObjectType({
name: 'Mail',
fields: () => ({
id: { type: new GraphQLNonNull(GraphQLID), },
...
})
const Query = {
mails: {
type: new GraphQLList(MailType),
args: {
senderId: { type: GraphQLID },
isOffline: { type: GraphQLBoolean },
},
async resolve(root, args, req, ctx) {
if (args.isOffline === false) {
let a = await model.aggregate([
{ $match: { isOffline: false } },
]);
let b = await model.find({ isOffline: false });
console.log(JSON.stringify(a) == JSON.Stringify(b)) /// return true
return a // error
return b // working
}
return model.find({senderId: args.senderId});
}
}
}
// with a
"errors": [
{
"message": "Cannot return null for non-nullable field Mail.id."
}]
I am in trouble for 2 hours but I do not get the answer.
Can anybody help me?
You probably have a mistake in your mongodb schema, not in graphQl.
make sure you did not define you id by id key, it should be _id.
for example if you are using mongoose it can be something like this:
const MailSchema = new Schema({
_id: {
type: String,
unique: true,
},
....
....
});

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

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