What should I do to stop the post request from posting new object if the object already exists?
I have pasted my code and json object. I have tried next(); but it doesnt work and a duplicate object with some other id is created no matter what. I am using before beforePostTransaction function to check if the product already exists. The request contains the id and the store id of the
index.js
const Transaction = require('./transactions/TransactionModel');
const TransactionCTL = require('./transactions/TransactionController');
Transaction.before('post', TransactionCTL.beforePostTransaction);
Transaction.register(router, '/transactions');
TransactionController.js
const beforePostTransaction = (req, res, next) => {
var id = req.body.id;
Transaction.findById(
id,
(err, data)=>{
if (!data){
next();
}
else{
var store = data.store;
store = JSON.stringify(store);
store = store.replace(/\"/g, "");
if(store !== req.body.store){ //update the whole object
next();
}
else{
//do what?
}
}
});
res.sendStatus(409);
}
json object
[{
"_id": "596db06849822a13c97ba3f9",
"store": "596b088131ea400490897c50"
}]
Not sure what is your model. But if it is mongoose you can use method
.findOneAndUpdate(query,
update,
{upsert: true},
function (error, result) {
if (!error) { //if you need to do something else
}
});
Where update is your object. It will create new item if it not exist and update it if it exist.
Related
I am stuck trying to update MongoDB with added req.body.whatever data.
When I get the req.body data to my route, I can see it, change it and update to the database just fine, but when I add say, a new element into the req.body like so:
req.body.newData = "this is new";
In the route, it will not populate into MongoDB with the rest of the existing (changeable) req.body data that already exists in the DB document.
I can in code change an existing req.body.(KeyElement), and updates fine to the DB. Once I try to add an element to req.body, the new one just doesn't get updated. Tried all different update, modify, replaceOne etc and can get an editable result, but still no new elements being added to the database. I even tried the
Model.update(query, {$set: req.body}); etc
and this seems to update as well but nothing new gets added.
Here is the route I'm working with...
router.post('/set-repair-info', ensureAuthenticatedAdmin, function(req, res) {
console.log('set-repair-info : ');
var ObjectId = require('mongodb').ObjectID;
var b = req.body;
console.log('body: ');
console.log(req.body);
var repairToUpdate = req.body.jid;
// console.log(repairToUpdate);
// console.log('req.body[uid]');
// console.log(req.body.jid);
// console.log('userid::: ' + req.body.userid);
// console.log('backuped : ' + req.body.backedup);
// console.log(req.body.username);
//buggy without this;
if (req.body.backedup=='false'){
req.body.backedup == '';
}
//CHECKS AND RESPONSES:
//by Edit
//PARTS ORDERED
if(req.body.repairstatus == 'Parts Ordered'){
req.body.partsordered = 'true'; //THIS WILL NOT GO INTO DB!
} else{
req.body.partsordered = null;
}
req.body.testthisout = "THIS IS A TEST"; //THIS WILL NOT GO INTO DB!
console.log("parts: " + req.body.partsordered);
// Job.replaceOne({ _id: ObjectId(req.body.jid)}, req.body , {upsert: true}, function (err, result) {
// (err === null) ? {msg: 'something happened... err edit user'} : {msg: err}
// });
console.log('body updated: ');
console.log(req.body);
req.body.repairstatus = "Waiting For Something Else"; // UPDATES FINE
Job.update({ _id: ObjectId(req.body.jid)}, { $set: req.body }, function (err, result) {
(err === null) ? {msg: 'something happened... err edit user'} : {msg: err}
});
req.flash('success_msg','Repair has successfully been edited and saved to the database.');
res.render('edit-repair', { job: {'data': req.body} });
});
Double check your Models Schema and make sure variable is setup there.
Check your routes that create an instance of the Schema, make sure value is in there. And .save() or update through mongoose method.
SAVE the file.
I have a small JSON file
{
"users": [
{
"id": 1111,
"name": "Foo",
"gold": 2
},{
"id": 2222,
"name": "Bar",
"gold": 7
}
]
}
and want to manipulate the data of one specific object, selected by its id.
I want to
read the data from the file
manipulate the data
write the new data back to the file
send a response to the client
so I went for this route, called by using Ajax
app.get('/incG/:id', function (req, res) {
fs.readFile('./database.json', 'utf8', function (err, data) {
var json = JSON.parse(data); // Read the data
var users = json.users; // Get all users
var user = users.find(u => u.id === Number(req.params.id)); // get the user by id
user.gold++; // increase his value
fs.writeFile('./database.json', , (err) => { // the second parameter is missing!
res.send(user.gold); // send a response to the client
});
});
});
As you can see, when using fs.writeFile(database, , (err) => { the second parameter is missing.
What do I have to pass in there? I just want to update one specific user object (one specific value).
EDIT
When passing in JSON.stringify(user) as a parameter I delete all the data in the file and just write down the new object. So this might not work this way.
Try this,
fs.readFile('./database.json', 'utf8', function (err, data) {
var json = JSON.parse(data); // Read the data
var users = json.users; // Get all users
var userGold;
users.find(u => {
if (u.id === Number(req.params.id)) {
userGold = u.gold++;
}
});
users = JSON.stringify(users);
fs.writeFile('./database.json', users, (err) => {
res.send(userGold);
});
});
fs.writeFile(file, data[, options], callback)
Pass stringified JSON as second argument.
app.get('/incG/:id', function(req, res) {
fs.readFile('./database.json', 'utf8', function(err, data) {
var json = JSON.parse(data); // Read the data
var users = json.users; // Get all users
var user = users.find(u => u.id === Number(req.params.id)); // get the user by id
user.gold++; // increase his value
var dataToWrite = JSON.stringify(user);
fs.writeFile('./database.json', dataToWrite, (err) => { // the second parameter is missing!
res.send(user.gold); // send a response to the client
});
});
});
I can't figure out how I delete data in another MongoDB scheme when I create.
I'm running on mean.js stack.
exports.create = function(req, res) {
var sign = new Sign(req.body);
sign.save(function(err) {
if (err) {
return res.status(400).send({
message: errorHandler.getErrorMessage(err)
});
} else {
sign.timesheets.forEach(function(entry) {
console.log(entry._id);
});
res.jsonp(sign);
}
});
};
Here I make a call to create a sign. Sign includes some strings and an array 'timesheets' with timesheet objects.
I also got a scheme for timesheets, I want to delete all timesheets objects that are included in my sign from timesheets scheme.
Here is my timesheets delete controller:
exports.delete = function(req, res) {
var timesheet = req.timesheet;
timesheet.remove(function(err) {
if (err) {
return res.status(400).send({
message: errorHandler.getErrorMessage(err)
});
} else {
res.jsonp(timesheet);
}
});
};
How do I call this from min sign controller, for each timesheet in sign?
Edit:
Route:
module.exports = function(app) {
var sign = require('../../app/controllers/sign.server.controller');
var timesheets = require('../../app/controllers/timesheets.server.controller');
app.route('/sign')
.post(sign.create, timesheets.deleteAll);
delete all
exports.deleteAll = function(req, res) {
var timesheet = req.timesheet;
timesheet.timesheets._id.forEach(function(entry) {
entry.remove(function(err) {
console.log(entry);
if (err) {
return res.status(400).send({
message: errorHandler.getErrorMessage(err)
});
} else {
res.jsonp(entry);
}
});
});
};
It runs and I can see id in the console, but it doesn't delete anything.
If you've implemented this as an array of TimesheetSchema documents inside each SignSchema document, then deleting the parent document would take everything that's part of it with it.
If you stored it as an array of ids referencing a document in another collection, then you'd have to go through those one by one and remove them as well. But I think it's better to go with the first approach if you don't need to do anything fancy. This was you can handle the removal easily, and it makes better sense semantically and performance-wise to retrieve everything you need to handle a "sign" in one go.
My query is:
db.Room.find({}, function (err, rooms) {
if (!err) {
async.each(rooms, function (room, done) {
db.User.find({}, function (err, users) {
if (err) {
done(err)
} else {
room.users = users
room._name = room.name
done()
}
})
}, function (err) {
if (!err) {
socket.emit('read:rooms', rooms)
}
})
}
})
and schemas are:
room:
var mongoose = require('mongoose')
var Schema = mongoose.Schema,
ObjectId = Schema.ObjectId;
var Room = new Schema({
name: String
});
module.exports = Room
user:
var mongoose = require('mongoose')
var Schema = mongoose.Schema,
ObjectId = Schema.ObjectId;
var User = new Schema({
email: String
});
module.exports = User
but in front-end:
socket.on('read:rooms', function (rooms) {
$scope.rooms = rooms
})
but rooms has no users property, help me, please
It's because the Rooms schema doesn't have a users property.
So, there are a few ways to fix it. Since it looks like though you want the users property to be something that really isn't part of the schema, and is a client-side join rather than work that is done on the database (which is a good!), I'd suggest you convert the data to be just plain old JavaScript objects when you send it over the socket (this would have happened anyway, you're just doing it a bit earlier).
So, when the find returns, it is actually returning a fully-realized MongooseJS model object. While you can set dynamic properties on the object instance, they aren't part of the "data" of the model, so that when it is serialized later to the client, only the properties that are documented will be available.
So, here is an example of what I'd suggest:
db.Room.find({}, function (err, rooms) {
if (!err) {
var oRooms = [];
async.each(rooms, function (room, done) {
/* etc. your code */
} else {
var oRoom = room.toObject();
oRoom.users = users
oRoom._name = room.name
oRooms.push(oRoom);
done()
}
This technique would use the toObject functionality of a Model to return a JavaScript object (not a Mongoose model). That way, you can do what you'd like to the object, including adding new properties dynamically.
Later, of course, make sure you send the new array of rooms to the client:
if (!err) {
socket.emit('read:rooms', oRooms)
}
I use NodeJS to insert documents in MongoDB. Using collection.insert I can insert a document into database like in this code:
// ...
collection.insert(objectToInsert, function(err){
if (err) return;
// Object inserted successfully.
var objectId; // = ???
});
// ...
How can I get the _id of inserted object?
Is there any way to get the _id without getting latest object inserted _id?
Supposing that in same time a lot of people access the database, I can't be sure that the latest id is the id of object inserted.
A shorter way than using second parameter for the callback of collection.insert would be using objectToInsert._id that returns the _id (inside of the callback function, supposing it was a successful operation).
The Mongo driver for NodeJS appends the _id field to the original object reference, so it's easy to get the inserted id using the original object:
collection.insert(objectToInsert, function(err){
if (err) return;
// Object inserted successfully.
var objectId = objectToInsert._id; // this will return the id of object inserted
});
There is a second parameter for the callback for collection.insert that will return the doc or docs inserted, which should have _ids.
Try:
collection.insert(objectToInsert, function(err,docsInserted){
console.log(docsInserted);
});
and check the console to see what I mean.
As ktretyak said, to get inserted document's ID best way is to use insertedId property on result object. In my case result._id didn't work so I had to use following:
db.collection("collection-name")
.insertOne(document)
.then(result => {
console.log(result.insertedId);
})
.catch(err => {
// handle error
});
It's the same thing if you use callbacks.
I actually did a console.log() for the second parameter in the callback function for insert. There is actually a lot of information returned apart from the inserted object itself. So the code below explains how you can access it's id.
collection.insert(objToInsert, function (err, result){
if(err)console.log(err);
else {
console.log(result["ops"][0]["_id"]);
// The above statement will output the id of the
// inserted object
}
});
if you want to take "_id" use simpley
result.insertedId.toString()
// toString will convert from hex
Mongo sends the complete document as a callbackobject so you can simply get it from there only.
for example
collection.save(function(err,room){
var newRoomId = room._id;
});
You could use async functions to get _id field automatically without manipulating data object:
async function save() {
const data = {
name: "John"
}
await db.collection('users').insertOne(data)
return data
}
Returns (data object):
{
_id: '5dbff150b407cc129ab571ca',
name: 'John',
}
Now you can use insertOne method and in promise's result.insertedId
#JSideris, sample code for getting insertedId.
db.collection(COLLECTION).insertOne(data, (err, result) => {
if (err)
return err;
else
return result.insertedId;
});
Similar to other responses, you can grab the variable using async await, es6+ features.
const insertData = async (data) => {
const { ops } = await db.collection('collection').insertOne(data)
console.log(ops[0]._id)
}
Another way to do it in async function :
const express = require('express')
const path = require('path')
const db = require(path.join(__dirname, '../database/config')).db;
const router = express.Router()
// Create.R.U.D
router.post('/new-order', async function (req, res, next) {
// security check
if (Object.keys(req.body).length === 0) {
res.status(404).send({
msg: "Error",
code: 404
});
return;
}
try {
// operations
let orderNumber = await db.collection('orders').countDocuments()
let number = orderNumber + 1
let order = {
number: number,
customer: req.body.customer,
products: req.body.products,
totalProducts: req.body.totalProducts,
totalCost: req.body.totalCost,
type: req.body.type,
time: req.body.time,
date: req.body.date,
timeStamp: Date.now(),
}
if (req.body.direction) {
order.direction = req.body.direction
}
if (req.body.specialRequests) {
order.specialRequests = req.body.specialRequests
}
// Here newOrder will store some informations in result of this process.
// You can find the inserted id and some informations there too.
let newOrder = await db.collection('orders').insertOne({...order})
if (newOrder) {
// MARK: Server response
res.status(201).send({
msg: `Order N°${number} created : id[${newOrder.insertedId}]`,
code: 201
});
} else {
// MARK: Server response
res.status(404).send({
msg: `Order N°${number} not created`,
code: 404
});
}
} catch (e) {
print(e)
return
}
})
// C.Read.U.D
// C.R.Update.D
// C.R.U.Delete
module.exports = router;