Nested data collection via function in mongoose - express

I don't know if its a dumb way to do this but I have a problem with this get route.
I want to get all the data from mongo in the lower part (find).
In that part I want to sum all data in the database.
for context: I want to display all datasets on the website and all the data as a sum.
Any idea why this isn't working?
router.get('/', function(req, res, next) {
function getSumme(){
stopp.aggregate([
{$group: {
_id: null,
totalLiter: {$sum: "$liter"}
}}
]);
console.log(summe);
};
stopp.find((err, data) => {
if (!err) {
res.render(path + '/index', {
data: data,
test: 123,
stopps: getSumme()
});
} else {
console.log('Failed to retrieve the Course List: ' + err);
}
});
})

Few corrections in your query,
missed async/await method for aggregate query
result the sum by checking turnery operator condition
router.get('/', async function(req, res, next) {
let result = await stopp.aggregate([
{
$group: {
_id: null,
totalLiter: {$sum: "$liter"}
}
}
]);
res.render(path + '/index', {
// data: data,
// test: 123,
stopps: result.length ? result[0].totalLiter : 0
});
})

Related

Express how to append queries with the same property?

Right now im trying to write a query deconstruction, it should look like this
describe("Deconstruct query params", () => {
it("should deconstruct the desired query param such as id=1,2,3,4 into id=1&id=2&id=3&id=4", async () => {
const req: RequestCustom = {
extra : {
user: {}
},
query: {
id: "1,2,3,4",
},
};
const res = {};
const next = jest.fn();
await deconstructQueryParams(["id"])(
(req as unknown) as express.Request,
res as express.Response,
next
);
expect(req.query).toEqual(
"id=1&id=2&id=3&id=4"
);
});
});
For this I try and use
export const deconstructQueryParams = (params: Array<string>) => async (
req: Request,
res: Response,
next: NextFunction
) => {
params.forEach((param) => {
if (req.query[param]) {
const paramArr = req.query[param].split(",");
delete req.query[param]
paramArr.forEach((value: string) => {
req.query.append(param, value); //append doesnt exist
});
}
});
next();
}
The problem with this, is that I cant use
req.query.id=1
req.query.id=2
.....
Because those queries will be replaced, when I need "id=1&id=2&id=3&id=4"
But apparently req.query.append doesnt exist, so I cant duplicate the query properties? How can I do so?

Graphql, node.js and sql,Cannot return null for non-nullable field

I want to return data coming from db to the api. The data is being logged but not showing on the graphql api.
const express = require('express');
const bodyParser = require('body-parser');
const graphqlHttp = require('express-graphql');
const { buildSchema } = require('graphql');
var mysql = require('mysql');
const app = express();
//start mysql connection
var connection = mysql.createConnection({
host : 'localhost', //mysql database host name
user : 'root', //mysql database user name
password : '', //mysql database password
database : 'test' //mysql database name
});
connection.connect(function(err) {
if (err) throw err
})
//end mysql connection
app.use(bodyParser.json());
app.use(
'/graphql',
graphqlHttp({
schema: buildSchema(`
type users {
id: String!
username: String!
password: String!
role: String!
name: String!
photo: String!
}
type RootQuery {
getUsers: [users!]!
}
type RootMutation {
createUsers(name: String): String
}
schema {
query: RootQuery
mutation: RootMutation
}
`),
rootValue: {
getUsers: () => {
connection.query('select * from users', function (error, results, fields) {
if (error) throw error;
console.log(JSON.stringify(results))
return JSON.stringify(results) ;
});
},
createUsers: (args) => {
const eventName = args.name;
return eventName;
}
},
graphiql: true
})
);
app.listen(3000);
RESULT:
query
{
getUsers {
id
}
}
OUTPUT:
{
"errors": [
{
"message": "Cannot return null for non-nullable field RootQuery.getUsers.",
"locations": [
{
"line": 3,
"column": 3
}
],
"path": [
"getUsers"
]
}
],
"data": null
}
This is your resolver:
getUsers: () => {
connection.query('select * from users', function (error, results, fields) {
if (error) throw error;
//users = results;
console.log(JSON.stringify(results));
return JSON.stringify(results) ;
});
},
A GraphQL resolver must return either a value or a Promise that will resolve to a value. However, here, you're not returning either. Keep in mind that callbacks are invoked asynchronously, so returning a value inside a callback does nothing (in most cases).
You really should use something like promise-mysql instead of mysql, but you can still wrap a callback with a Promise and return that Promise. Something like this should work:
getUsers: () => {
// Note, we have to return the Promise here
return new Promise((resolve, reject) => {
connection.query('select * from users', (error, results, fields) => {
if (error) {
reject(error)
} else {
// Don't stringify
resolve(results)
}
})
})
},
getUsers: () => {
/* 👉 return 👈 */ connection.query('select * from users', function (error, results, fields) {
if (error) throw error;
//users = results;
console.log(JSON.stringify(results));
return JSON.stringify(results) ;
});
},
Your getUsers function doesn't return anything. I believe you're missing the return statement I've highlighted in the above comment.
Incidentally, it's best practices in GraphQL to ensure all the root fields (such as getUsers) are nullable, have a read of this article to find out why.
delete (!) from field definition in schema

Express and Sequelize: Set foreign key in router post

I am trying to make it so that when a post request to /api/routines is called, a row in the routines table is created and sets the userId foreign key to the current user. Here is my Routine model:
const Routine = db.define('routine', {
name: {
type: Sequelize.STRING,
allowNull: false,
validate: {
notEmpty: true
}
}
})
Here is my associations:
User.hasMany(Routine)
Routine.belongsTo(User)
And here is my router post method:
router.post('/', async (req, res, next) => {
try {
const routine = await Routine.create({
name: req.body.Title
})
const user = await User.findOne({ where: { id: req.body.user } })
await routine.setUser(user) //This is where I need help! This line doesn't work
await user.hasOne(routine)
res.json(routine)
} catch (err) {
next(err)
}
})
I am not sure how to add a foreign key linking the routine to the user. Let me know if you have any ideas. Thanks.
I have an app that, I think, does what you want. First you'll need to keep the ID of who's logged in in your context. To do this, I have the following imports in my src/index.js file:
import models, { sequelize } from './models';
import routes from './routes';
Then, further down in that same file, I have the following code:
app.use(async (req, res, next) => {
req.context = {
models,
me: await models.User.findByLogin(username),
};
next();
});
Where the username variable holds the name of the currently logged in user.
Then, I have an answer end-point where users can post answers, which is similar to your routine end-point. The posting route looks as follows in my case:
router.post('/', async (req, res) => {
const answer = await req.context.models.Answer.create({
text: req.body.text,
userId: req.context.me.id,
});
return res.send(answer);
});
As you can see, I am posting the answer text and the user ID all at once. In your case, I think it would look as follows:
router.post('/', async (req, res, next) => {
try {
const routine = await Routine.create({
name: req.body.Title,
userId: req.context.me.id
});
return res.json(routine);
} catch (err) {
next(err)
}
})
Note that you will have to adjust userId in the code above to whatever field name you are using.

Express API - select one id from database

i want to know how can i realize passing parameter to Model. I have 3 file server.js , controllers/news.js and models/news.js
Server.js
const newsController = require('./controllers/news');
server.get('/newsAll', newsController.all);
server.post('/getOneNews', (req, res) => {
db.get().query(`SELECT * FROM news WHERE id = ?`, [ req.body.id ],
(err, result, fields) => {
if (err) console.log('error SELECT one row', err);
});
});
controller/news.js
const newsModule = require('../models/news');
exports.all = (req, res) => {
newsModule.all((err, rows) => {
if (err) {
console.error(err);
return res.sendStatus(500);
}
res.send(rows);
});
};
models/news.js
const db = require('../db');
exports.all = (done) => {
db.get().query(`SELECT * FROM news ORDER BY id`, (err, rows) => {
if (err) {
console.log('error SELECT * FROM news MYSQL', err);
throw err;
}
done(err, rows);
});
};
All about method all i understood , but i want to know how can i passing [ req.body.id ] (<- from front-end) this parametr to Model for accepting ONE news from database . Whithout parameters it is very easy.
All you need is to do is grab the id from the req.params object and then set your endpoint to accept that params value.
// Server.js
server.get('/getOneNews/:id', (req, res) => {
db.get().query(`SELECT * FROM news WHERE id = ?`, [ req.params.id ],
(err, result, fields) => {
if (err) console.log('error SELECT one row', err);
});
});
Hope this helps!

expressjs doesn't wait till query is done

I am using expressjs to retrieve data from elasticsearch and send back to my angular app at the front end. Currently I am facing a problem since expressjs doesn't wait until the query execution is finished. I searched for a solution for that and the community says use "Promise or Sync". But I cant figure out where should I use it. I tried to use it but I am getting errors.
This is where I am receiving the request from the frontend and calling the elasticsearch query for send the response.
api.post('/clsDependencies', (req, res) => {
classDependencies(req.body.className);
res.json(messages);
});
This the function for querying the elasticsearch.
function classDependencies(csName) {
let body = {
size: 20,
from: 0,
query: {
match: {
ClassName: {
query: csName
}
}
}
};
search('testclass', body)
.then(results => {
results.hits.hits.forEach((hit, index) => hit._source.dependencies.forEach(
function(myClass){
messages.push({text: myClass.methodSignature , owner: `\t${++nmb} -
${myClass.dependedntClass}`});
}))})
.catch(console.error);
};
Expected data gets initialized to the variable(messages) which I am trying to send back to the front end. But the variable doesn't get initialized at the time when response is send back. What Should I do to wait till the query execution finish before send back the data to frontend.
EDIT
messages is defined outside of both functions.
function classDirectory(className) {
let body = {
size: 20,
from: 0,
query: {
match: {
ClassName: {
query: className
}
}
}
};
return search('testclass', body).then(results => {
results.hits.hits.forEach((hit, index) =>
getDirectories(hit._source.JarFileName));
return messages;
})
.catch(function(err) {
// log the error, but keep the promise rejected
console.error(err);
throw err;
});
};
function getDirectories(jarName) {
let body = {
size: 20,
from: 0,
query: {
match: {
jarFileName: {
query: jarName
}
}
}
};
return search('testjar', body).then(results => {
results.hits.hits.forEach((hit, index) =>
messages.push({text: hit._source.jarFileName , owner: `\t${++nmb} -
${hit._source.directory}`})
);
return messages;
})
.catch(function(err) {
// log the error, but keep the promise rejected
console.error(err);
throw err;
});
};
The Javascript interpreter does not "block" when you make asynchronous calls. This has absolutely nothing to do with Express.
Your call to search() is non-blocking so while it's in process, classDependencies() returns and the rest of your code continues to run. This is the way asynchronous calls in Javascript work.
If you want to call res.json() when classDependencies() is done, then return a promise from it and call res.json() when that promise resolves.
You could do something like this:
api.post('/clsDependencies', (req, res) => {
classDependencies(req.body.className).then(messages => {
res.json(messages);
}).catch(err => {
res.status(500).send(something here);
});
});
function classDependencies(csName) {
let body = {
size: 20,
from: 0,
query: {
match: {
ClassName: {
query: csName
}
}
}
};
return search('testclass', body).then(results => {
let messages = [];
results.hits.hits.forEach((hit, index) => hit._source.dependencies.forEach(function(myClass) {
messages.push({
text: myClass.methodSignature,
owner: `\t${++nmb} - ${myClass.dependedntClass}`
});
}));
// make messages be the resolved value of the returns promise
return messages;
}).catch(function(err) {
// log the error, but keep the promise rejected
console.error(err);
throw err;
});
};
api.post('/clsDirectory', (req, res) => {
classDependency(req.body.className, res);
});
function classDependency(csName, cb) {
let body = {
size: 20,
from: 0,
query: {
match: {
ClassName: {
query: csName
}
}
}
};
search('testclass', body)
.then(results => {
results.hits.hits.forEach((hit, index) =>
hit._source.dependencies.forEach(
function(myClass){
messages.push({text: myClass.methodSignature , owner: `\t${++nmb} -
${myClass.dependedntClass}`});
}));
cb.json(messages);
})
.catch(console.error);
};