node.js and mongodb increment _id sequentially in existing database - node.js

Good morning everyone.
So I'm doing a class assignment wherein I'm connecting to an existing mongoDB database (via a node.js server), and I'm adding a bunch of data to it from a form on an HTML site. I've got the form information adding correctly, but there's two fields server side that aren't responding to new data. There is the primary key (_id) which instead of incrementing from the current last number, get's incremented by ObjectId('longnumericvale'), and CustomerID which get's populated by an undefined value. The last record existing in the database has both _id and CustomerId as the same number. How can I get node.js to look at this number and auto increment it when it's adding my form data as a new document in the mongodb DB. Code below:
app.post("/orderform", (req, res) => { //This takes post action from html and stores it
console.log("successfully posted")
var item = {
CustFirstName: req.body.CustFirstName,
CustLastName: req.body.CustLastName,
CustAddress: req.body.CustAddress,
CustCity: req.body.CustCity,
CustProv: req.body.CustProv,
CustPostal: req.body.CustPostal,
CustCountry: req.body.CustCountry,
CustHomePhone: req.body.CustHomePhone,
CustBusPhone: req.body.CustBusPhone,
CustEmail: req.body.CustEmail,
userid: req.body.userid,
passwd: req.body.passwd,
};
console.log("Customer information stored as:");//this is just a debug to the console to make sure it's grabbing the info
console.log(item);
//here we connect to the datbase, and insert every item above to its corresponding position in the "customers" collection of "travelexperts" database
mongo.connect(mongoUrl, { useNewUrlParser: true, useUnifiedTopology: true },
(err, client) => {
if (err) throw err;
//select database
const db = client.db("travelexperts");
//grab a collection
const collection = db.collection("customers");
collection.insertOne(item, (err, res) => {
if (err) throw err;
console.log("Items inserted");
db.close;
});
});//endconnection
res.redirect('/thanks');
console.log("finished, redirected")
});
//render thank you page for after submitting order
app.get('/thanks', (req, res) =>{
res.render("thanks");
});
I've read the documentation for mongodb on autoincrementing, but it's a bit beyond me how to implement it in my specific example.
UPDATE
So maybe I didn't explain the problem really well. I'm trying to log into two separate collections now, and I have that working. with this code below:
app.post("/orderform", (req, res) => { //This takes post action from Order.html form and stores all form inputs with corresponding names in a variable called item
console.log("successfully posted")
var item = {
CustFirstName: req.body.CustFirstName,
CustLastName: req.body.CustLastName,
CustAddress: req.body.CustAddress,
CustCity: req.body.CustCity,
CustProv: req.body.CustProv,
CustPostal: req.body.CustPostal,
CustCountry: req.body.CustCountry,
CustHomePhone: req.body.CustHomePhone,
CustBusPhone: req.body.CustBusPhone,
CustEmail: req.body.CustEmail,
userid: req.body.userid,
passwd: req.body.passwd,
};
console.log("This should be an array of all entered customer info:");//this is just a debug to the console to make sure it's grabbing the info
console.log(item);
var book = {
BookingId: "",
BookingDate: new Date(),
BookingNo: "",
TravelerCount:"",
CustomerId: "",
TripTypeId:"",
PackageId: Number(req.query.packId),
};
console.log(book);
//here we connect to the datbase, and insert every item/booking above to its corresponding position in the "customers" collection of "travelexperts" database
mongo.connect(mongoUrl, { useNewUrlParser: true, useUnifiedTopology: true },
(err, client) => {
if (err) throw err;
const db = client.db("travelexperts");
const collection = db.collection("customers");
const booking = db.collection("bookings");
collection.insertOne(item, (err, res) => {
if (err) throw err;
console.log("Items inserted");
});
booking.insertOne(book, (err, res) => {
if (err) throw err;
console.log("Items inserted");
});
db.close;
});//endconnection
res.redirect('/thanks');
console.log("finished, redirected")
});
So the issue is that for both collections and bookings, they have incomplete records. collections is 26 documents long, and the last _id is 144. So that's why I need to read that _id and increment it +1 for each new record. There's an _id field for each collection and then a customerId and BookinbId that should match it. Really appreciate all the help so far, but neither of these solutions seems to work. I tried both just before the collections.insertone line, and i tried console logging them and they just return [object Object] in the console instead of the _id value.

To insert a custom ID field for your documents, you should append the _id field with your item object.
The simplest wayc can be to create a global id_counter variable that you increment everytime you execute the /orderform API.
let idCounter = 1;
.
.
.
const itemDoc = {_id: idCounter++, ...item}
collection.insertOne(itemDoc, (err, res) => {
if (err) throw err;
console.log("Items inserted");
db.close;
});
.
.
.
You could also fetch the last inserted Item's id and simply increment it and it could save a lot of effort to keep the ids of the documents in sync incase the server restarts or something.
In that case, you could do something as below using collection.countDocuments() method:
let docLength = 0 // global variable
.
.
.
// inside your api endpoint controller...
collection.countDocuments({}, {}, (err, res)=> {
docLength = res;
})
const itemDoc = {_id: docLength++, ...item}
collection.insertOne(itemDoc, (err, res) => {
if (err) throw err;
console.log("Items inserted");
db.close;
});

Related

MongoDB CRUD routes returning null or wrong values

I've recently started using the MEAN stack and stumbled upon some errors while trying to work with my MongoDB database. I connected to the database successfully, implemented my CRUD routes, and I get wrong values for anything besides the find() method (which returns all the documents in my collection without any problem). The findOne() looks like this for example:
router.route(server.get("/company/:id", (request, response) => {
const companyId = request.params.id;
console.log("Showing company with id: " + companyId)
dbCollection.findOne({ _id: mongodb.ObjectId(companyId) }, (error, result) => {
if (error) throw error;
// return company
response.json(result);
});
}));
The result after making a get request via Postman is null
The insertOne() looks like this:
router.route(server.post("/company/add", (request, response) => {
const company = request.body;
dbCollection.insertOne(company, (error, result) => {
if (error) throw error;
// return updated list
dbCollection.find().toArray((_error, _result) => {
if (_error) throw _error;
response.json(_result);
});
});
}));
It adds one document to the database with the ID that it creates for itself, but for some reason it doesn't take in the body data (2 string elements { "name": "xy", "type": "company" })
And last but not least, the deleteOne():
router.route(server.delete("/company/delete/:id", (req, res) => {
const companyId = req.param.id;
console.log("Delete company with id: ", companyId);
dbCollection.deleteOne({ _id: mongodb.ObjectId(companyId) }, function(err, result) {
if (err) throw err;
// send back entire updated list after successful request (optional)
dbCollection.find().toArray(function(_err, _result) {
if (_err) throw _err;
res.json(_result);
});
});
}));
For some reason it deletes the very first document in the collection, but not the one that is entered with the corresponding ID.
If anyone could help me out with this it would be awesome. Thank you in advance!
Edit 1:
Adding a new document to the collection via Postman
Collection after the add
Edit 2:
Get request via ID and response (returns null)
Console output:
Showing company with id: 5e63db861dd0ce2418ce423d
Edit 3:
Corrected the code for the findOne() and deleteOne() methods.
When you try with _id you need to convert the string(request.params.id) to ObjectId().
Convert string to ObjectID in MongoDB - whoami

Post same objectID in to different table

I'm trying to post a data in my user then at the same time, post the _id of my user as a reference id in my donation table.
After I posted my data in the users table like this:
var User = require('../models/user');
var Blooddonation = require('../models/blooddonation');
router.post('/createBlooduser',function(req, res) {
var user = new User();
user.user_lastname = req.body.user_lastname;
user.status= "initial";
user.save(function(err) {});
});
How can I get the _id of the posted data and make a reference id in my donation table? Something like this:
**users.json**
{
_id:ObjectId("5c7e591eee959272cc5768cb"),
user_lastname:"Jhonson",
status:"initial"
}
**blooddonations.json**
{
donor_id:ObjectId("5c7e591eee959272cc5768cb")
}
The _id property is actually created as soon as you create new instance with a statement like new User(). So you can actually access that value before it's even stored in the collection, or at any time after instance creation really:
router.post('/createBlooduser',function(req, res) {
var user = new User();
user.user_lastname = req.body.user_lastname;
user.status= "initial";
user.save(function(err) {
if (err) throw err; // or really handle better
// You can also just create() rather than new Blooddonation({ donor_id: user._id })
Blooddonation.create({ donor_id: user._id }, function(err, donor) {
// check for errors and/or respond
})
});
});
Of if you might just want access to other properties that might "default on save", then you can access in the callback from save() or create():
router.post('/createBlooduser',function(req, res) {
User.create({
user_lastname: req.body.user_lastname;
status: "initial"
}, function(err, user) { // this time we pass from the callback
if (err) throw err; // or really handle better
Blooddonation.create({ donor_id: user._id }, function(err, donor) {
// check for errors and/or respond
});
});
});

Mongoose $addToSet return new list entrys

I have a question working with mongoose 4.0.1
I am trying to add new picture objects to an array inside a model. This is the code of my endpoint that is actually doing the job:
// Add new images
exports.pictures = function(req, res) {
Incident.findByIdAndUpdate(
req.params.id,
{$addToSet: {"pictures": {$each: req.body}}},
{new: true},
function(err, incident) {
if (err) { return handleError(res, err); }
return res.send(201).json(incident.pictures);
}
);
};
The problem: The callback object (incident) stores all information of the model which was found and updated. But I want to return only the new array entries which were created.
How can I receive the actual changes of the operation instead of the whole object that is storing the pictures array?
I solved the problem by creating a new schema for pictures and adding a reference to the incident model.
The endpoint changed as well:
Create new picture instances for a array of pictures
Find incident by id
Save the references of the picture instances to a array inside the incident
Return the id of the picture instances
var _ = require('lodash');
// Add new images
exports.pictures = function(req, res) {
Picture.create(req.body, function(err, pictures) {
if (err) { return handleError(res, err); }
Incident.findByIdAndUpdate(
req.params.id,
{$addToSet: {"pictures": {$each: pictures}}},
function(err) {
if (err) { return handleError(res, err); }
var pictureIds = _.map(pictures, '_id');
return res.status(201).json(pictureIds);
}
);
});
};

Cannot applying find() method with Native MongoDB becaus of ID type

I have a function that is needed to get results.
When I give 1 as _id filter everything is OK.
collectionPersonnel
.find({ '_id' : 1 })
.toArray(function (err, personnel) {
console.log(personnel);
});
If I give filter another way for instance user[0]['personnel_id'] -that is store 1- then I get only [] result;
collectionPersonnel
.find({ '_id' : user[0]['personnel_id'] })
.toArray(function (err, personnel) {
console.log(personnel);
});
And then I've tried another way. But it doesn't work because I used a string(user[0]['personnel_id']) instead of an ObjectID.
var ObjectID = require('mongodb').ObjectID;
var personnelPK_Hex = (user[0]['personnel_id']).toHexString();
var personnelPK = ObjectID.createFromHexString(personnelPK_Hex);
What should I do?
Edit
All of my codes are below;
module.exports = {
show: function(req, res) {
User.native(function(err, collectionUser) {
if(err) {
console.log("There is no exist a User by current_id");
};
collectionUser
.find({'_id' : req.param('id')})
.toArray(function (err, user) {
Personnel.native(function(err, collectionPersonnel) {
if(err) {
// handle error getting mongo collection
console.log("There is no exist a Personel by current _id");
};
if(!collectionPersonnel) {
console.log("There is no exist a Personel by current _id");
};
// var ObjectID = require('mongodb').ObjectID;
// var personnelPK_Hex = (user[0]['personnel_id']).toHexString();
// var personnelPK = ObjectID.createFromHexString(personnelPK_Hex);
collectionPersonnel
.find({ '_id' : user[0].personnel_id })
.toArray(function (err, personnel) {
console.log(personnel);
});
});
});
});
}
};
And console's output is;
[]
Solved
Just like apsillers's said. I had given a numeric _id to collection, incorrectly.
I've fixed _id value and everything is OK.
Thank you all...
user[0]['personnel_id'] might be a string. For Mongo, "1" is different from 1, which is why your literal number 1 worked, but your variable (which holds a string) does not.
Instead, try using a unary plus to convert the string to a number: +user[0]['personnel_id'].
try to use like user[0].personal_id instead of user[0]['personnel_id'] please provide your schema design that would be better to figure out what exactly you are missing.
i tried like this
collectionPersonnel
.find({ '_id' : user[0].personnel_id })
.toArray(function (err, personnel) {
console.log(personnel);
});

MongoDB two same records

I'm doing a project which is backed by Nodejs and MongoDB. I am quite new to MongoDB and I am lacking a clue why I quite often(almost always) get two same records in collections when I do posts. The two records only differ by ID, which are for example ObjectId("53aefb0fc68a0810504d2066") and 53aefb0fc68a0810504d2066, is this normal or am I doing something wrong? Thanks for any pointers.
Here is some node code:
server.js:
app.post("/:collection", function (req, res) {
var object = req.body;
var collection = req.params.collection;
collectionDriver.save(collection, object, function (err, docs) {
if (err) {
res.send(400, [err, object]);
} else {
res.send(201, docs);
}
});
});
collectionDriver:
save: function(collectionName, obj, callback) {
this.getCollection(collectionName, function(error, the_collection) {
if( error ) callback(error);
else {
obj.created_at = new Date();
the_collection.insert(obj, function() {
callback(null, obj);
});
}
});
},
getCollection: function(collectionName, callback) {
this.db.collection(collectionName, function(error, data) {
if (error) {
callback(error);
} else {
callback(null, data);
}
});
},
Everytime you ask MongoDB to save an object without an _id field, it automatically generates a new, globally unique ObjectID for that field and saves the object under that ObjectID.
When you want to use save to update an existing document, you need to make sure that the _id field is populated with the _id of the document you want to update.
Alternatively, you can create an unique index on those fields you consider relevant for determining what's a duplicate and what isn't. However, in that case an attempt to save an already existing document will throw an error instead of replacing the document.

Resources