Cloud Datastore and Node.js: Cannot get entity - node.js

I am using App Engine flexible environment with Node.js and am trying to store and retrieve entities in Cloud Datastore.
The following code successfully creates a new Event Entity:
/* Create event */
router.post('/', function(req, res, next) {
const eventKey = datastore.key('Event');
datastore.save({
key: eventKey,
data: req.body
})
.then(() => {
console.log('New event created');
res.json({id: eventKey.id});
})
.catch((err) => { next(err); });
});
However, the following returns an empty array when I provide the previously returned id:
/* Get an event */
router.get('/:id', function(req, res, next) {
console.log(req.params.id);
var eventKey = datastore.key(['Event', req.params.id]);
datastore.get(eventKey)
.then((event) => {
console.log(event);
res.json(event);
})
.catch((err) => { console.log(err); next(err); });
});
I seem to be using datastore.get correctly and to do what the docs is telling me to do.
Any idea why I cannot get the entity I previously created?

It's worth noting that Cloud Datastore keys ([Ancestor path +] kind + id/name) treat integers (id) and strings (name) differently. That is to say that the following 2 keys refer to different entities:
Key(Event, 1234)
Key(Event, "1234")
I'm not a node expert, but is it possible it is writing and reading these different keys?
parseInt can solve this:
/* Get an event */
router.get('/:id', function(req, res, next) {
console.log(req.params.id);
var eventId = parseInt(req.params.id, 10)
var eventKey = datastore.key(['Event', eventId]);
datastore.get(eventKey)
.then((event) => {
console.log(event);
res.json(event);
})
.catch((err) => { console.log(err); next(err); });
});

Related

How do I get the ID of the document I just inserted into MongoDB? (API)

I am trying to get the ID of the document that I just inserted into mongoDB. Here is the node.js code:
app.post("/groups/new", (req, res) => {
const dbGroup = req.body;
Groups.create(dbGroup, (err) => {
if (err) {
res.status(500).send(err);
} else {
var id = dbGroup._id;
res.status(201).send(id);
}
});
});
I have tried various things, like adding a group to the function:
app.post("/groups/new", (req, res) => {
const dbGroup = req.body;
Groups.create(dbGroup, (err, group) => {
if (err) {
res.status(500).send(err);
} else {
var id = group._id;
res.status(201).send(id);
}
});
});
But that also does not work, so I tested if my even get the API response on the front end with:
res.status(201).send("test");
Which works perfectly fine. So I don't know why this doesn't work, because all the documentation says this is the way.
I figured a way to get the id. It may be not the most efficient way, because it sends all the data it gets but it gets the job done.
Backend:
app.post("/groups/new", (req, res) => {
const dbGroup = req.body;
Groups.create(dbGroup, (err, data) => {
if (err) {
res.status(500).send(err);
} else {
res.status(201).send(data);
}
});
});
Front end:
axios.post("/groups/new", {
groupname: roomName,
}).then((res) => {
roomid = res.data._id;
});

Express - Accessing the values in post request to use in my get request

Reworded due to lack of clarity.
I have my post request method
app.post("/api/animals", (req, res, next) => {
const search = new Search({
gps: req.body.gps
});
var search1 = JSON.stringify(req.body.gps);
console.log(search1);
console.log(search);
search.save();
res.status(201).json({
message: 'Search Successful'
});
});
and my get request method
app.get('/api/animals',(req, res, next) => {
const search = new Search({
gps: req.body.gps
});
var search1 = JSON.stringify(req.query.gps);
console.log(search1)
Animal.find({})
.then(documents => {
res.status(200).json({
message: 'Complete Sucess',
animals: documents
});
});
});
I want to use the data I am posting search or search1 in my Animal.find() method in my get request. How can I make this data available to use in app.get or have it so when data is posted it searches automatically?
Thanks!
It sounds like you want to re-use the Animal.find( code in two places. Is that correct?
Something like this?
function findAnimals(criteria) {
return Animal.find(criteria);
}
app.post("/api/animals", (req, res, next) => {
// ...
findAnimals(search).then(documents => {
res.status(200).json({
message: 'Complete Sucess',
animals: documents
});
});
app.get('/api/animals',(req, res, next) => {
// ...
findAnimals(search).then(documents => {
res.status(200).json({
message: 'Complete Sucess',
animals: documents
});
});

ExpressJS Mongoose render view after getting data from database

I need to render view after mongodb provide data from database. I write this code but the main problem is view is generated before getting data.
router.get('/', async(req, res, next)=> {
try{
const products = await Product.find({});
res.render('shop/index', { title: 'Express',products });
}catch(e){
console.log(e);
}
});
You could try doing something like this:
router.get("/", async (req, res, next) => {
Product.find({}, (err, items) => {
if (err) {
console.log(err);
res.status(500).send("An error occurred", err);
} else {
res.render("home", { items });
}
});
});
Actually everything looks great, idk why it's not working. I probably write something like this:
router.get("/", async (req, res) => {
const products = await Product.find({});
if (!products) return res.render("error");
res.render("shop/index", {
title: "Express",
products
});
});

GET request for specific id returning null

I'm attempting to build a simple CRUD application using express and mongodb. My GET request for all database entries is working and my POST request is working but I can't seem to figure out the problem with my GET request for individual entries.
Server.js GET request:
app.get('/api/:id', function (req, res) {
var id = req.params.id;
db.collection('api').findOne({_id: id}, (err, result) => {
if (err){
res.sendStatus(404);
return console.log(err);
}
res.redirect('/');
return console.log(result);
});
});
When I type 'url/api/593555074696601afa192d7f' which is an ID I know exists the console.log is returning null, I'm not sure if I'm doing something wrong?
You should pass ObjectID instance in the query.
let ObjectID = require("mongodb").ObjectID;
app.get('/api/:id', function (req, res) {
var id = req.params.id;
db.collection('api').findOne({_id: ObjectID(id)}, (err, result) => {
if (err){
res.sendStatus(404);
return console.log(err);
}
res.redirect('/');
return console.log(result);
});
});
Give Mongoose a try. It might be of help if your models get complex.

NodeJs - calling one method from another in server controller

With the following controller, how can I call one method from another in the same controller?
Specifically, calling login() within a successful signup(), while retaining the same functionality for login() when it is used by a form?
The line this.login(newUser) does not work, nor does plain old login(newUser)
In both scenarios, I get the error:
TypeError: Cannot call method 'login' of undefined
var mongoskin = require('mongoskin');
module.exports = {
login: (function (req, res) {
req.db.collection('auth').findOne({_id: mongoskin.helper.toObjectID(req.body.id)},
function (err, results) {
// log person in and send results to client
}
)
}),
signup: (function (req, res) {
var user = req.body;
req.db.collection('auth').insert(user, function (err, newUser) {
// after adding user, automatically log them in
// does not work:
//login(newUser, function (err) {
// do something
//})
// does not work:
this.login(newUser, function (err) {
// do something
})
}
)
})
}
Controllers should be doing as little as possible, and should orchestrate the work required by executing functions stored elsewhere.
View this gist - click here
What I have done is created "services" that are not tied to the client request, therefore re-usable everywhere.
Hope this helps.
Thanks to Dave Newton
var mongoskin = require('mongoskin');
var myCollection = 'auth';
Solution
function localLogin(db, myCollection, user, res){
db.collection(myCollection).findOne({_id: mongoskin.helper.toObjectID(user._id)},
function(err, user){
res.send({ token: createToken(user) });
});
module.exports = {
login: (function (req, res) {
var user = req.body;
localLogin(req.db, myCollection, user, res)
},
signup: (function (req, res) {
var user = req.body;
req.db.collection(myCollection).insert(user, function (err, newUser) {
// after adding user, automatically log them in
localLogin(req.db, myCollection, newUser, res)
})
}
) }) }

Resources