Parse: ParseError { code: 101, message: 'Object not found.' } - javascript

I have a cloud function running some code like this and I am able to get a response for my query which is a valid class instance, but when I try to update the instance with the set method, I get the error you see in the title.
async function addToDB(apiKey) {
const query = new Parse.Query(MyClass);
query.equalTo('apiKey', apiKey);
const response = await query.find({ useMasterKey: true });
const myInstance = response[0];
myInstance.set('total', 100);
try {
await myInstance.save({ useMasterKey: true });
} catch (e) {
console.log('E', e);
}
}

the options parameter ( { useMasterKey : true}) should be the second parameter passed to save
the first parameter to a save should be a null, i.e. :
myInstance.save(null, { useMasterKey: true })
in essence, you are not passing the masterkey option in to the save call - which is why you are getting the 101 error (in my experience, a 101 is almost always related to permissions issues!)
see more here http://parseplatform.org/Parse-SDK-JS/api/v1.11.1/Parse.Object.html#save

Related

forEach not working as expected in NodeJs

I am uploading the excel sheet in DB with the help of Nodejs, I am unable to authenticate and return the error as already exists the userid when the item.USER_ID already exists in DB. my server goes crashes and returns an error as Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
Please help in the code how I fix this issue and make it, If the item.USER_ID already exists return error else insert.
var XLSX = require("xlsx");
const fs = require("fs");
try {
const transaction = await con.transaction();
var workbook = XLSX.readFile("myfile.xlsx");
let json_data = XLSX.utils.sheet_to_json(workbook.Sheets.Sheet1);
let count = 0;
json_data.map(async (item) => {
let stmt1 = await con.query("SELECT * FROM `table` WHERE `user_id` = :userid", { replacements: { userid: item.USER_ID }, type: con.QueryTypes.SELECT });
if (stmt1.length > 0) {
await transaction.rollback();
return res.json({ message: "already exist the userid" });
} else {
let stmt2 = await con.query("INSERT INTO `table` (`user_id` , `user_name`) VALUES ( :user_id , :user_name)", {
replacements: {
user_id: item.USER_ID,
user_name: item.USER_NAME,
},
type: con.QueryTypes.INSERT,
transaction: transaction,
});
count++;
if (count == json_data.length) {
await transaction.commit();
return res.json({ message: "file uploaded successfully.." });
}
}
});
} catch (err) {
await transaction.rollback();
return res.json({ code: 500, message: { msg: "SQL ERROR" }, error: err.stack, status: "error" });
}
Here in your code, you are calling the res.json({ message: "file uploaded successfully.." }) inside json_data.map function.
since you are calling the res.json function inside an array, it'll be called as many times as of elements present in the array and as we know, we can sent only 1 response at a time for a request.
Because of which you're catching the errors Cannot set headers after they are sent to the client
just remove that res.json inside the map function, add it at the last of that particular map function.
I know you might question for the condition count == json_data.length you added to the code but javascript is async and this particular block can be executed before to that.
Hope this answer helps you! Please comment if you get any errors or have questions.

Express.js - Cannot Set Headers with exported function

Learning how to do testing with Express with using Mocha, Chai, Chai-HTTP plugin, and MongoDB with Mongoose. I have a test to purposely detect if MongoDB will send back an error from trying to find a document using a faulty _id value (too short).
I noticed that part of my code is repeating around my other Express routes, and want to reuse it for other routes so I exported it from another module, but now I get this:
Uncaught Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
Not sure why I am getting this error. If I have the same code, as the exported function, inside the route code it works fine, but exported it just complains.
Here is the code:
test/route/example.test.js Snippit
it('Bad request with a too short ID string (12 characters minimum)', () => {
// /api/v1/example is the endpoint
// /blah is the param
chai.request(app).get('/api/v1/example/blah').end((err, res) => {
// Insert all the nice assert stuff. :)
});
});
route/example.js Snippit
// Packages
const router = require('express').Router();
// Models (Mongoose Schemas)
const Example = require('../models/example.model');
// Helpers
const { foundMongoError } = require('../helpers/routes');
// -----Snipped-----
router.route('/:exampleId').get((req, res) => {
// Retrieve the exampleId parameter.
const exampleId = req.params.exampleId;
Example.findById(exampleId, (mongoError, mongoResponse) => {
foundMongoError(mongoError, res); // Having an issue
// If I have the same code that makes up foundMongoError inside here, no issues,
// but it will no longer be DRY.
// Check if any responses from MongoDB
if(mongoResponse) {
res.status(200).json(mongoResponse);
} else {
return res.status(404).json({
errorCode: 404,
errorCodeMessage: 'Not Found',
errorMessage: `Unable to find example with id: ${exampleId}.`
});
}
});
});
helpers/routes.js
const foundMongoError = (mongoError, res) => {
if(mongoError) {
return res.status(400).json({
errorCode: 400,
errorCodeMessage: 'Bad Request',
errorMessage: mongoError.message
});
}
};
module.exports = {
foundMongoError
};
That just means you send and response res twice back. The first time you send it back at here:
if(mongoError) {
return res.status(400).json({
errorCode: 400,
errorCodeMessage: 'Bad Request',
errorMessage: mongoError.message
});
}
You sended an response back but the function still continue its work, that means the function moves on till here then:
if(mongoResponse) {
res.status(200).json(mongoResponse);
} else {
return res.status(404).json({
errorCode: 404,
errorCodeMessage: 'Not Found',
errorMessage: `Unable to find example with id: ${exampleId}.`
});
}
Here happens the second response, and here you get the error.
I would rewrite the code like this:
Instead of returning the response, you return an true that means there is an error, otherwise false :
const foundMongoError = (mongoError, res) => {
if(mongoError) {
res.status(400).json({
errorCode: 400,
errorCodeMessage: 'Bad Request',
errorMessage: mongoError.message
});
return true;
}
return false;
};
module.exports = {
foundMongoError
};
Then you can write it like this:
if(foundMongoError(mongoError, res)) return;
The return will stop the function to execute the rest of the code

meteor methods functions return is not working

I am trying if my data is removed then show return "removed successfully"; but it's not working also not removing the data. If I am not used function then data is removed but not getting any return result form call back
Its working
Meteor.methods({
removeFAV: function(userID, product_id) {
Favorites.remove(
{ user_id: userID, product_id: product_id },
{ multi: true }
);
}
});
It's not working
Meteor.methods({
removeFAV: function(userID, product_id) {
Favorites.remove(
({ user_id: userID, product_id: product_id }, { multi: true }),
function(err) {
if (err) {
return err;
} else {
return "removed successfully";
}
}
);
}
});
The Meteor Mongo.Collection is not a native Mongo Collection but a wrapper that integrates native Mongo calls into the Meteor environment.
See: https://docs.meteor.com/api/collections.html#Mongo-Collection
The insert update and remove methods have a specific blocking behavior unless you provide a callback:
On the server, if you don’t provide a callback, then remove blocks until the database acknowledges the write and then returns the number of removed documents, or throws an exception if something went wrong.
If you do provide a callback, remove returns immediately. Once the remove completes, the callback is called with a single error argument in the case of failure, or a second argument indicating the number of removed documents if the remove was successful.
https://docs.meteor.com/api/collections.html#Mongo-Collection-remove
Since the blocking type call is automatically throwing en error, there is theoretically no need to explicitly handle the exception:
Meteor.methods({
removeFAV: function(userID, product_id) {
const removedDocs = Favorites.remove(
{ user_id: userID, product_id: product_id },
{ multi: true });
// remove returns the number of docs being removed
return `removed [${removedDocs}] document(s) successfully`
}
});
Such a method will return in the callback of Meteor.call either the thrown error as first parameter or the result as second.
However, it also makes sense to handle the exception and let the method fail silently:
Meteor.methods({
removeFAV: function(userID, product_id) {
let removedDocs = 0
try {
// remove returns the number of docs being removed
removedDocs = Favorites.remove(
{ user_id: userID, product_id: product_id },
{ multi: true });
} catch (e) {
// log error
myErrorLog.log(e)
} finally {
return `removed [${removedDocs}] document(s) successfully`
}
}
});
This will never return an error to the client but logs the error on the server.

Meteor asynchronous call within Accounts.createUser

Before registering a new User I need to delete a previous one with that email and query an API to fill more information into User as a product requirement.
Unfortunately I can not achieve it, this is the error I get from the server: Exception while invoking method 'createUser' Error: insert requires an argument.
What I did so far is this:
Client:
Accounts.createUser({ email, password, profile: { something } }, (err) => {
if (err) {
console.error(err2.reason);
}
history.replace('/account');
});
Server:
Accounts.onCreateUser((options, user) => {
Meteor.users.remove({ email: options.email }, () => {
try {
const res = request.postSync(authenticate, {
method: 'POST',
json: true,
body: {
email: options.email,
password: options.profile.password
}
});
if (res.response.statusCode < 300) {
const newUser = user;
newUser.profile = {};
newUser.profile.user_id = res.body.response.user_id;
newUser.profile.token = res.body.response.token;
return newUser;
}
throw new Meteor.Error(res.response.body.error.message);
} catch (err) {
throw new Meteor.Error(err.message);
}
});
});
What I'm doing wrong? Thanks
From the Accounts.onCreateUser documentation:
The function should return the user document (either the one passed in or a newly-created object) with whatever modifications are desired. The returned document is inserted directly into the Meteor.users collection.
You function returns nothing though, it just calls Meteor.users.remove() with some function as second argument. Don't forget that DB calls are synchronous in Meteor, so it should be like this:
Accounts.onCreateUser((options, user) => {
Meteor.users.remove({ email: options.email });
// do something else
return user;
});

Mongoose - Create document if not exists, otherwise, update- return document in either case

I'm looking for a way to refactor part of my code to be shorter and simpler, but I don't know Mongoose very well and I'm not sure how to proceed.
I am trying to check a collection for the existence of a document and, if it doesn't exist, create it. If it does exist, I need to update it. In either case I need to access the document's contents afterward.
What I've managed to do so far is query the collection for a specific document and, if it's not found, create a new document. If it is found, I update it (currently using dates as dummy data for this). From there I can access either the found document from my initial find operation or the newly saved document and this works, but there must be a better way to accomplish what I'm after.
Here's my working code, sans distracting extras.
var query = Model.find({
/* query */
}).lean().limit(1);
// Find the document
query.exec(function(error, result) {
if (error) { throw error; }
// If the document doesn't exist
if (!result.length) {
// Create a new one
var model = new Model(); //use the defaults in the schema
model.save(function(error) {
if (error) { throw error; }
// do something with the document here
});
}
// If the document does exist
else {
// Update it
var query = { /* query */ },
update = {},
options = {};
Model.update(query, update, options, function(error) {
if (error) { throw error; }
// do the same something with the document here
// in this case, using result[0] from the topmost query
});
}
});
I've looked into findOneAndUpdate and other related methods but I'm not sure if they fit my use case or if I understand how to use them correctly. Can anyone point me in the right direction?
(Probably) Related questions:
How to check if that data already exist in the database during update (Mongoose And Express)
Mongoose.js: how to implement create or update?
NodeJS + Mongo: Insert if not exists, otherwise - update
Return updated collection with Mongoose
Edit
I didn't come across the question pointed out to me in my searching, but after reviewing the answers there I've come up with this. It's certainly prettier, in my opinion, and it works, so unless I'm doing something horribly wrong I think my question can probably be closed.
I would appreciate any additional input on my solution.
// Setup stuff
var query = { /* query */ },
update = { expire: new Date() },
options = { upsert: true };
// Find the document
Model.findOneAndUpdate(query, update, options, function(error, result) {
if (!error) {
// If the document doesn't exist
if (!result) {
// Create it
result = new Model();
}
// Save the document
result.save(function(error) {
if (!error) {
// Do something with the document
} else {
throw error;
}
});
}
});
You are looking for the new option parameter. The new option returns the newly created document(if a new document is created). Use it like this:
var query = {},
update = { expire: new Date() },
options = { upsert: true, new: true, setDefaultsOnInsert: true };
// Find the document
Model.findOneAndUpdate(query, update, options, function(error, result) {
if (error) return;
// do something with the document
});
Since upsert creates a document if not finds a document, you don't need to create another one manually.
Since you wish to refactor parts of your code to be shorter and simpler,
Use async / await
Use .findOneAndUpdate() as suggested in this answer
let query = { /* query */ };
let update = {expire: new Date()};
let options = {upsert: true, new: true, setDefaultsOnInsert: true};
let model = await Model.findOneAndUpdate(query, update, options);
///This is simple example explaining findByIDAndUpdate from my code added with try catch block to catch errors
try{
const options = {
upsert: true,
new: true,
setDefaultsOnInsert: true
};
const query = {
$set: {
description: req.body.description,
title: req.body.title
}
};
const survey = await Survey.findByIdAndUpdate(
req.params.id,
query,
options
).populate("questions");
}catch(e){
console.log(e)
}
Here is an example I am using. I have to return custom responses for UI updates etc. This can be even shorter. User is
const UserScheme = mongoose.Schema({
_id: String,
name: String,
city: String,
address: String,
},{timestamps: true});
const User = mongoose.model('Users', UserScheme);
async function userUpdateAdd(data){
var resp = '{"status": "error"}';
if(data){
var resp = await User.updateOne({ _id: data._id }, data).then(function(err, res){
console.log("database.userUpdateAdd -> Update data saved in database!");
if(err){
var errMessage = err.matchedCount == 0 ? "User Record does not exist, will create new..." : "Record not updated";
// If no match, create new
if(err.matchedCount == 0){
const create_user = new User(data);
resp = create_user.save().then(function(){
console.log("database.userUpdateAdd -> Data saved to database!");
return '{"status":"success", "message": "New User added successfully"}';
});
return resp;
}
// Exists, return success update message
if(err.matchedCount == 1){
return '{"status": "success", "message" : "Update saved successfully"}';
} else {
return '{"status": "error", "code": "' + err.modifiedCount + '", "message": "' + errMessage + '"}';
}
}
})
.catch((error) => {
//When there are errors We handle them here
console.log("database.userUpdateAdd -> Error, data not saved! Server error");
return '{"status": "error", "code": "400", "message": "Server error!"}';
});
}
return resp;
}
Here's an example:
const mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/rsvp', {useNewUrlParser: true, useUnifiedTopology: true});
const db = mongoose.connection;
db.on('error', () => {
console.log('mongoose connection error');
});
db.once('open', () => {
console.log('mongoose connected successfully');
});
const rsvpSchema = mongoose.Schema({
firstName: String,
lastName: String,
email: String,
guests: Number
});
const Rsvp = mongoose.model('Rsvp', rsvpSchema);
// This is the part you will need... In this example, if first and last name match, update email and guest number. Otherwise, create a new document. The key is to learn to put "upsert" as the "options" for the argument.
const findRsvpAndUpdate = (result, callback) => {
Rsvp.findOneAndUpdate({firstName: result.firstName, lastName: result.lastName}, result, { upsert: true }, (err, results) => {
if (err) {
callback(err);
} else {
callback(null, results);
}
})
};
// From your server index.js file, call this...
app.post('/rsvps', (req, res) => {
findRsvpAndUpdate(req.body, (error, result) => {
if (error) {
res.status(500).send(error);
} else {
res.status(200).send(result);
}
})
});

Categories

Resources