Return data from two models - javascript

Hello, guys. Please help me. How I can get 'topics' array and append it to res.view(). I tried many variants. But always in 'topics' I got 'undefind'.
Subjects.query("SELECT `subjects`.`id`, `subjects`.`name` AS `subject` FROM `subjects`
WHERE `subjects`.`faculty` = " + faculty_id, function (err, subs)
{
subs.forEach(function(subject, topics)
{
var topics = new Array();
Topics.query("SELECT `topics`.`id`, `topics`.`name` AS `topic` FROM `topics`
WHERE `topics`.`subject` = " + subject.id, function (err, tops)
{
topics[subject.id] = tops;
});
console.log(topics);
});
res.view({
title: 'Private cabinet',
users: user[0],
subjects: subs,
});
});

I tried many variants, but only this works:
var async = require('async');
_ = require('lodash');
module.exports = {
'cabinet': function (req, res)
{
async.auto(
{
user: function(cb)
{
User.query("SELECT `users`.`email`, `users`.`id`, `users`.`name`, `users`.`surname`, `users`.`lastname`, `groups`.`name` as `group`, `faculties`.`name` as `faculty`, `faculties`.`id` AS `faculty_id` FROM `users`, `groups`, `faculties` WHERE `users`.`id` = " + req.session.user + " AND `users`.`group` = `groups`.`id` AND `faculties`.`id` = `groups`.`faculty` GROUP BY `users`.`id`", cb);
},
subjects: ['user', function(cb, async_data)
{
var faculty = async_data.user.map(function (item){return item.faculty_id});
Subjects.find()
.where({faculty: faculty})
.exec(cb);
}],
topics: ['subjects', function(cb, async_data)
{
var subject = async_data.subjects.map(function (item){return item.id});
Topics.find()
.where({subject: subject})
.exec(cb);
}]
},
function allDone (err, async_data)
{
if (err) return res.serverError(err);
var user = async_data.user;
var subjects = async_data.subjects;
var topics = async_data.topics;
_.map(user, function (user) {
var theseSubjects =
_.where(subjects, {faculty: user.faculty_id });
subjects = theseSubjects;
_.map(subjects, function (subject) {
var theseTopics =
_.where(topics, {subject: subject.id });
subject.topics = theseTopics;
});
});
res.view({
title: 'Личный кабинет',
user: user[0],
subjects: subjects
});
});
},

Related

MongoDB if field does not exist insert

i have category schema and i want to insert new category if category name does not exist. I tried something but i could not any response.
category.model
var mongoose = require("mongoose");
var categorySchema = mongoose.Schema({
name: {
type: String,
require: true
},
createdAt: {
type: Date,
default: () => {
return new Date();
}
}
});
module.exports = mongoose.model("category", categorySchema);
category insert function
var Category = require("../models/category.model");
exports.create = (req, res) => {
Category.find({ name: req.body.name }, (err, cat) => {
if (cat.length > 0) {
// i want to return exists message here
} else {
// i want to insert here if not exists
var category = new Category();
category.name = req.body.name;
category.save(err => {
if (err) {
return new response(null, err).error500(res);
}
return new response(category, null).created(res);
});
}
});
};
You can do it like this code below:
exports.create = async (req, res) => {
try {
let category = await Category.find({ name: req.body.name });
if(category) {
// return or do some stuff here
}
category = new Category(req.body);
category = await category.save();
return new response(category, null).created(res);
} catch(ex) {
console.log(ex.message);
return new response(null, ex).error500(res);
}
};
I hope it can help you.

How to return Boolean properly in different NodeJS files?

So I have files inside the following folder:
app/controller/token.js
app/controller/news.js
token.js:
"use strict";
var connection = require("../con");
exports.isTokenExists = function(token) {
var checkToken = "SELECT COUNT(`id`) AS 'total' FROM `user` WHERE `token` = '" + token + "'";
var isExists = false;
var count;
var checkResult;
connection.query(checkToken, function(error, rows) {
if (!error) {
checkResult = JSON.parse(JSON.stringify(rows));
for (var i = 0; i < checkResult.length; i++) {
var row = rows[i];
count = row.total;
}
if (count > 0) {
isExists = true;
}
}
});
return isExists;
};
news.js:
"use strict";
var response = require("../response/responses");
var connection = require("../con");
var getToken = require("./token");
exports.news = function(req, res) {
response.send(false, "News API", null, res);
};
exports.allNews = function(req, res) {
var checkTokenExists = getToken.isTokenExists("75d12cc4dc07608d5b87a6cba33cac056df1239c");
if (checkTokenExists) {
var allNewsQuery = "SELECT a.`id`, b.`title` AS `category`, a.`title`, a.`description`, a.`content`, a.`image`, a.`created_date` FROM `news` AS a LEFT JOIN `news_category` AS b ON a.`id_news_category` = b.`id` ORDER BY `created_date` DESC LIMIT 20";
connection.query(allNewsQuery, function(error, rows) {
if (error) {
response.send(true, "" + error, null, res);
} else {
var data = [];
var newsData = JSON.parse(JSON.stringify(rows));
for (var i = 0; i < newsData.length; i++) {
var row = rows[i];
data[i] = {
id: row.id,
idCategory: row.idCategory,
category: row.category,
title: row.title,
description: row.description,
image: row.image,
createdDate: row.created_date
};
}
response.send(false, "News is not empty", data, res);
}
});
} else {
response.send(true, "Error: Token not found", checkTokenExists, res);
}
};
I always getting false value from isTokenExists meanwhile the token is exists in the table.
How do I get true response if the token is exist and how do I get false response if the token is not exists in table?
Any help will be much appreciated.
Regards.
The issue here is that connection.query accepts a callback, but the rest of your code will move passed that without awaiting the result, which is why your isExists always returns false. You can fix this by encapsulating the query with a Promise like this:
"use strict";
const connection = require("../con");
exports.isTokenExists = async function(token) {
const checkToken = "SELECT COUNT(`id`) AS 'total' FROM `user` WHERE `token` = ?";
return new Promise((resolve, reject) => {
connection.query(checkToken, token, function (error, results) {
if (error) return reject(error);
return resolve(results.length > 0);
});
});
};
I also simplified the logic in the callback a bit.
Then, in news.js await the result like this:
exports.allNews = async function(req, res) {
getToken.isTokenExists("75d12cc4dc07608d5b87a6cba33cac056df1239c")
.then(result => {
if (result === true) {
//place your code for handling if the token exists here
}
else {
//place your code for handling if the token does not exist
}
})
.catch(err => {
//handle error
});
}
You are missing async / await concept. You need to wait until your query executes.
1) Write a promise function
export.getCount = function(query) {
return new Promise((res, rej) => {
let count = 0;
connection.query(checkToken, function(error, rows) {
if (!error) {
checkResult = JSON.parse(JSON.stringify(rows));
for (var i = 0; i < checkResult.length; i++) {
var row = rows[i];
count = row.total;
}
}
return res(count);
})
}
2) Write async function which supports await operations
exports.isTokenExists = async function(token) {
var query = "SELECT COUNT(`id`) AS 'total' FROM `user` WHERE `token` = '" + token + "'";
let count = await getCount(query)
return count > 0; // Returns true if count is > 0
};

Update fields in object with mongoose in mongodb

I have a simple collection in mongodb.
I use mongoose.
I have users model with one field type object.
And I want change this object dynamically. But this code doesn't work, I used findByIdAndUpdate(), findById, findOne(), findOneAndUpdate().
const UsersSchema = mongoose.Schema({
likes: {}
},
{ collection: 'users' });
const Users = mongoose.model('Users', UsersSchema);
const id ="5b4c540f14f353a4b9875af4";
const thems = ['foo', 'bar'];
Users.findById(id, (err, res) => {
thems.map(item => {
if (res.like[item]) {
res.like[item] = res.like[item] + 1;
} else {
res.like[item] = 1;
}
});
res.save();
});
I believe that, for solve this problem you need to add more fields in your schema:
I created one example with this data:
const UsersSchema = new mongoose.Schema({
likes :[
{
thema:{
type: String
},
likes_amount:{
type: Number
},
_id:false
}]
});
module.exports = mongoose.model('Users', UsersSchema);
I added one user:
var newUser = new UserModel({
likes:[{
thema:'foo',
likes_amount:1
}]
});
newUser.save();
Here the code that increment the likes per thema:
const thems = ['foo', 'bar'];
const userId = "5b4d0b1a1ce6ac3153850b6a";
UserModel.findOne({_id:userId})
.then((result) => {
var userThemas = result.likes.map(item => {
return item.thema;
});
for (var i = 0; i < thems.length; i++) {
//if exists it will increment 1 like
if (userThemas.includes(thems[i])) {
UserModel.update({_id: result._id, "likes.thema" : thems[i]}, {$inc: {"likes.$.likes_amount": 1}})
.then((result) => {
console.log(result);
}).catch((err) => {
console.log(err)
});
} else {
//if doesn't exist it will create a thema with 1 like
UserModel.update({_id: result._id},
{
$addToSet: {
likes: {
$each: [{thema: thems[i], likes_amount: 1}]
}
}})
.then((result) => {
console.log(result);
}).catch((err) => {
console.log(err)
});
}
}
}).catch((err) => {
console.log(err)
});
Database result of this increment:
I hope that it can help you.

KOA2+node+ejs Error: Can't set headers after they are sent

Use kOA2 + node js + ajax to grab the web page data and display the result information on the front page:
query.js
const superagent = require('superagent');
const charset = require('superagent-charset');
const cheerio = require('cheerio');
charset(superagent);
function Rate(from, to, queryNumber) {
this.from = from;
this.to = to;
this.queryNumber = queryNumber;
}
module.exports = Rate;
Rate.query = function query(rate, callback) {
let URL = 'http://qq.ip138.com/hl.asp?from=' + rate.from + '&to=' + rate.to + '&q=' + rate.queryNumber;
superagent.get(URL)
.charset('gbk')
.end((err, sres)=> {
if (err) {
return next(err);
}
var $ = cheerio.load(sres.text);
var queryResult = [];
queryResult[0] = $(".rate td").eq(4).text();
queryResult[1] = $(".rate td").eq(5).text();
callback(null, queryResult);
})
};
index.js
const index = require('koa-router')();
const Rate = require('../models/query');
index.get('/s*', async (ctx, next) => {
let rate = new Rate(ctx.query.from, ctx.query.to, ctx.query.queryNumber);
await Rate.query(rate, (err, queryResult) => {
if (err) {
return next(err);
} else {
return ctx.render('query', {
title: '查询结果',
rate: queryResult[0],
amount: queryResult[1]
});
return next();
}
});
when visit “/s*” page, appear:(Node: 808) UnhandledPromiseRejectionWarning: Unhandled hate rejection (rejection id: 1): Error: Can not set headers after they are sent. Error, and the page can not jump.
Tried a lot of ways, but still do not know where to return in advance.
Is now known, because after the end of ctx, but also to call render to write data. The The But that is not where to change. Pls Help me.
Please update
const index = require('koa-router')();
const Rate = require('../models/query');
index.get('/s*', async (ctx, next) => {
let rate = new Rate(ctx.query.from, ctx.query.to, ctx.query.queryNumber);
await Rate.query(rate, (err, queryResult) => {
if (err) {
return next(err);
} else {
return ctx.render('query', {
title: '查询结果',
rate: queryResult[0],
amount: queryResult[1]
});
return next();
}
});
to
const index = require('koa-router')();
const Rate = require('../models/query');
index.get('/s*', async (ctx, next) => {
let rate = new Rate(ctx.query.from, ctx.query.to, ctx.query.queryNumber);
await Rate.query(rate, (err, queryResult) => {
if (err) {
return next(err);
} else {
return ctx.render('query', {
title: '查询结果',
rate: queryResult[0],
amount: queryResult[1]
});
}
});

Mongoose findOne in stream callback not executed

When I execute a findOne query to a collection that is different than that of the surrounding stream, it doesn't really execute the callback (does 1 or 2). Here is my code:
schema.js:
'use strict';
var mongoose = require('mongoose'),
Schema = mongoose.Schema;
var AutocompleteSchema = new Schema({
nGram: String,
locations: [{ type: Schema.Types.ObjectId, ref: 'Location' }]
});
module.exports = mongoose.model('Autocomplete', AutocompleteSchema);
ingest.js:
var Autocomplete = require('./schema');
var nGramAPI = require('ngram');
var cache = [];
function storeNGram(input, location) {
if(cache.indexOf(input) === -1) {
cache.push(input);
Autocomplete
.findOne({ nGram: input })
.populate('locations')
.exec(function (err, nGram) {
console.log(nGram);
if(!nGram) {
var newAutocomplete = {
nGram: input,
locations: [location._id]
};
Autocomplete.create(newAutocomplete, function(err, created) {
cache.splice(cache.indexOf(input), 1);
});
}
else {
nGram.locations.push(location._id);
sortLocations(nGram);
location.save(function(err, saved){
cache.splice(cache.indexOf(input), 1);
});
}
});
}
else {
setTimeout(function() {
storeNGram(input, location);
}, 100);
}
}
exports.ingest = function() {
console.log("Building nGrams");
var stream = Location.find().stream();
stream.on('data', function (location) {
var length = location.dispName.length > 20 ? 20 : location.dispName.length;
for(var i = 1; i <= length; i++) {
_.each(nGramAPI(i)(location.dispName), function(nGram) {
storeNGram(nGram, location);
});
}
});
}
When I execute the Autocomplete.findOne on its own outside of the stream it queries properly, but when inside it fails. Any suggestions?

Categories

Resources