I have a NodeJS application which is using mongoosastic api for Elasticsearch. Now I need a way of adding a condition(isDeleted == false) to the specified query(query: req.query.q).
this is my code
exports.search = function (req, res) {
if (!req.query.q) return res.status(400).send('No Query Provided')
log.error(req.query.q)
User.search({query_string: {query: req.query.q}}, (err, results) => {
if (err) return handleError(res, err)
var ret = _.map(results.hits.hits, result => ({
userID: result._id,
_score: result._score,
name: result._source.name,
loc: result._source.loc,
info: result._source.info,
images: result._source.images
}))
return res.send(ret)
})
}
How can I do that?
You can use filtering to filter your data. Check the example of your plugin website. Following example is your answer also.
var geoQuery = {query_string: {query: req.query.q}};
var myFilter = {
term: {
isDeleted: true
}
};
User.search(geoQuery, {filter: myFilter}, function(err, res) { /* ... */ })
Related
I have a complicated problem with my Node/React app. I have a shopping cart with the final element when checking out is to add order details to my MySQL database, however my function is returning an error from the controller. I am posting the relevant code, the full code is too extensive for a post.
This is the Node route:
module.exports = function(app) {
var controller = require('../controllers/controller');
// controller Routes
app.route('/products')
.get(controller.list_all_products)
.post(controller.create_a_product);
app.route('/products/:product_type')
.get(controller.products_by_type);
app.route('/product/:productId')
.get(controller.read_a_product)
.put(controller.update_a_product)
.delete(controller.delete_a_product);
};
This is the relevant part of the controller:
exports.create_a_product = function(req, res) {
var new_product = new Product(req.body);
//handles null error
if(!new_product.product || !new_product.status){
res.status(400).send({ error:true, message: 'Please provide product/status' });
} else {
Product.createProduct(new_product, function(err, product) {
if (err)
res.send(err);
res.json(product);
});
}
};
The relevant part of the Model:
var Product = function(product){
this.product = product.product;
this.status = Product.status;
this.created_at = new Date();
};
Product.createProduct = function (newProduct, result) {
sql.query("INSERT INTO orders set ?", newProduct, function (err, res) {
if(err) {
console.log("error: ", err);
result(err, null);
}
else{
console.log(res.insertId);
result(null, res.insertId);
}
});
};
Then the React side uses this api call:
import $ from 'jquery'
export const addOrder = order => {
const urlString = "http://localhost:9000/products"
return $.ajax({
url: urlString,
method: "POST",
data: order,
success: () => {
console.log('order logged')
},
error: (status, err) => {
console.log(status)
}
})
}
And finally I make the call with this var:
var r = await addOrder(this.state.order).then(res => res.json())
The order details are a simple object:
this.state = {
order: {
oid: '',
order_date: '',
products: '',
first_name: '',
last_name: '',
email: '',
address: '',
city: '',
province: '',
zip: '',
country: ''
}
}
When executing I get the error 'Please provide product/status' from the controller.
I know this is a tough one, any help is hugely appreciated.
It seems to me that you send the order object to products service which may contain multiple products. You should extract products from the order object (req.body) and send them to createProduct method in a loop.
I am trying to use an api to get the current value of a stock and multiply by the users stock.
When I make a call the route I get empty data, and when I print the value of the callback I get an empty array
function user_cur_portfolio(port, callback) {
let portfolio = [];
port.forEach( (stock) => {
var ticker = stock.name.toLowerCase();
alpha.data.quote(`${ticker}`).then(data => {
var fixed = Number((data['Global Quote']['05. price'] * stock.shares).toFixed(2));
let curr = {
name : ticker,
shares: stock.shares,
value : fixed
}
portfolio.push(curr)
});
})
callback(portfolio)
}
router.get('/portfolio', (req, res, next) => {
if (req.session.userId !== undefined){
User.findOne({ _id : req.session.userId }).exec(function (err, user) {
if (err)
next(err);
user_cur_portfolio(user.portfolio, (port)=>{
console.log(port);
res.render('portfolio', { portfolio: port, balance: user.balance});
});
})
} else {
res.redirect('/users/login');
}
});
When I make a call the route I get empty data Because alpha.data.quote is an async function and forEach is a sync function therefore, you will not be getting data in port variable.
So the best work around to this, is to use async await with all the synchronous function to behave them like async
async function user_cur_portfolio(port) {
let portfolio = [];
await Promise.all(
port.map(async stock => {
var ticker = stock.name.toLowerCase();
const data = await alpha.data.quote(`${ticker}`);
var fixed = Number((data['Global Quote']['05. price'] * stock.shares).toFixed(2));
let curr = {
name: ticker,
shares: stock.shares,
value: fixed
};
portfolio.push(curr);
})
);
return portfolio;
}
router.get('/portfolio', (req, res, next) => {
if (req.session.userId !== undefined) {
User.findOne({ _id: req.session.userId }).exec(async function(err, user) {
if (err) next(err);
const port = await user_cur_portfolio(user.portfolio);
console.log(port);
res.render('portfolio', { portfolio: port, balance: user.balance });
});
} else {
res.redirect('/users/login');
}
});
I need to make two query's from different tables, how should i do it, to output data in new page. Now it is working with one query.
exports.getAllImages = function () {
return new Promise((resolve, reject) => {
con.query("SELECT * FROM products WHERE product_group='TRENCH
CONVECTORS'", function (err, result, fields) {
if (err) reject(err);
resolve(result);
});
});
}
//This is what i tried, but it does not work
router.get('/product/:id', async function(req, res, next) {
let filesFromFolder;
let allimages
database.retreaveImage(req.params.id).then(function(value) {
filesFromFolder = value;
});
database.getAllImages().then(function(value){
allimages = value;
})
res.render('product.ejs', {
productName: req.params.id,
data: filesFromFolder,
allimages: allimages
});
});
//This code works, and i am using it now
router.get('/product/:id', async function(req, res, next) {
let filesFromFolder;
database.retreaveImage(req.params.id).then(function(value) {
filesFromFolder = value;
res.render('product.ejs', {
productName: req.params.id,
data: filesFromFolder
});
});
});
How should i edit the code to execute two query's?
You need to render your page when you received response from both queries.
You can use Promise.all() method for this.
Promise.all([
database.retreaveImage(req.params.id),
database.getAllImages()
]).then(resultArr => {
filesFromFolder = resultArr[0];
allimages = resultArr[1];
res.render("product.ejs", {
productName: req.params.id,
data: filesFromFolder,
allimages: allimages
});
});
I'm not sure if you want a single query who retrieve data from two tables or if you want 2 different queries from 2 table...if the second, you can concatenate functions to have a linear flow of data
//This code works, and i am using it now
router.get('/product/:id/:temp', async function(req, res, next) {
let filesFromFolder;
database.retreaveImage(req.params.id).then(function(value) {
var filesFromFolder = value;
//Using a temp function
database.retreaveTemp(req.params.temp).then(function(value_temp) {
var filesFromTemp = value_temp;
res.render('product.ejs', {
productName: req.params.id,
data: filesFromFolder,
dataTemp: filesFromTemp
});
});
});
});
I used this method because I am storing an array of classified messages, I would like to vividly understand why it doesn't update.
Here's the db.js:
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const ObjectId = mongoose.Types.ObjectId;
const usersessionSchema = new Schema({
fb_id: String,
fb_name: String,
fb_profpic: String,
message_body: [
{
message: String,
message_type: String,
timestamp: String
}
],
admin: Boolean,
branch: String
});
const model = (prefix) => {
prefix = prefix || '';
console.log(prefix);
if (prefix.length > 0) {
return mongoose.model(prefix + "-usersessions", usersessionSchema);
} else {
return new Error('Undefined collection prefix!');
}
}
/** Push message into message body*/
module.exports.pushsession =
async(model, id, data) => {
return new Promise((resolve, reject) => {
console.log(data);
model.findOneAndUpdate({fb_id: id}, {$push: {data}},{safe: true})
.then(res => {
console.log(res);
/
resolve(res);
})
.catch(err => {
reject(err);
console.log(err);
throw err;
});
});
}
Here's the controller.js:
/** Push usersession message */
module.exports.pushsession =
async(req, res, next) => {
try {
//jwt.validateToken(req);
var en = "en";
var dateEn = moment().locale(en);
format = "MM/DD/YYYY h:mm:ss A"; //h:mm:ss.SSS if you want miliseconds
var datetime_now = dateEn.format(format);
console.log(datetime_now);
var request = {
message_body: {
message: req.body.message,
message_type: req.body.message_type,
timestamp: datetime_now
}
};
const model = usersessionDB(req.query['client']);
const id = req.body.fb_id;
const result = await usersessionDB.pushsession(model, id, request);
if (result) {
response.success(res, next, result, 200, response.HTTP_STATUS_CODES.ok);
} else {
response.failure(res, next, {
message: 'ID does not exist'
}, 404, response.HTTP_STATUS_CODES.not_found);
}
} catch (err) {
response.failure(res, next, err, 500, response.HTTP_STATUS_CODES.internal_server_error);
}
}
Here's the route.js:
const controller = require('../controller/usersession-controller');
module.exports =
(server) => {
server.post('/api/session', controller.create);
server.get('/api/session', controller.list);
server.get('/api/session/:id', controller.get);
server.put('/api/session/:id', controller.update);
server.del('/api/session/:id', controller.delete);
server.put('/api/pushsession', controller.pushsession);
}
Visually, if you run this using postman, you can see that it display the one I want to search and update
Result of the postman
What I want to happen is to insert another set of array inside that message_body
Data I've inserting
My desired output
This code is working without that promise something, but in my project it is needed so I can't remove that thing.
So, based on :
This code is working without that promise something
i can point a thing or two,
in db.js
module.exports.pushsession =
async(model, id, data) => {
return new Promise((resolve, reject) => {
you don't need async since you're returning a promise so replace this
async(model, id, data) => {
with
(model, id, data) => {
and since you're returning a promise and removed async , you don't need the await on the other side ( controller.js ), so this
const result = await usersessionDB.pushsession(model, id, request);
if (result) {
response.success(res, next, result, 200, response.HTTP_STATUS_CODES.ok);
} else {
should be
usersessionDB.pushsession(model, id, request).then(
(result) => { // when resolved
response.success(res, next, result, 200, response.HTTP_STATUS_CODES.ok);
},
(err) => { // when rejected
response.failure(res, next, {
message: 'ID does not exist'
}, 404, response.HTTP_STATUS_CODES.not_found);
});
this is a comparison between async/await and promises : Javascript Promises vs Async Await. Difference?
and here's some good examples of using promises : https://medium.com/dev-bits/writing-neat-asynchronous-node-js-code-with-promises-32ed3a4fd098
i think your $push is ok but you already said
This code is working without that promise something
i hope this helps and Good luck :)
I tried cleaning my code
here's the controller.js:
/** Push usersession message */
module.exports.pushsession =
async (req, res, next) => {
try {
//jwt.validateToken(req);
var en = "en";
var dateEn = moment().locale(en);
format = "MM/DD/YYYY h:mm:ss A"; //h:mm:ss.SSS if you want miliseconds
var datetime_now = dateEn.format(format);
console.log(datetime_now);
var data = {
message: req.body.message,
message_type: req.body.message_type,
timestamp: datetime_now
};
const model = usersessionDB(req.query['client']);
const id = req.body.fb_id;
console.log(id);
const result = await usersessionDB.pushsession(model, id, data).then(
(result) => { // when resolved
response.success(res, next, result, 200, response.HTTP_STATUS_CODES.ok);
},
(err) => { // when rejected
response.failure(res, next, {
message: 'ID does not exist'
}, 404, response.HTTP_STATUS_CODES.not_found);
});
} catch (err) {
response.failure(res, next, err, 500, response.HTTP_STATUS_CODES.internal_server_error);
}
}
Here's the db.js:
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const ObjectId = mongoose.Types.ObjectId;
const usersessionSchema = new Schema({
fb_id: String,
fb_name: String,
fb_profpic: String,
message_body:[{
message: String,
message_type: String,
timestamp: String
}],
admin: Boolean,
branch: String
});
/** Push message into message body*/
module.exports.pushsession =
async(model, id, data) => {
console.log(data);
return new Promise((resolve, reject) => {
model.findOneAndUpdate({fb_id: id}, { $push: { message_body: data }})
.then(res => {
console.log(res);
resolve(res);
})
.catch(err => {
reject(err);
console.log(err);
throw err;
});
});
}
Out of the blue after I tried to replace $push with $set then again I replace it with $push, it worked.
I don't if there's a difference, or I miss something, feel free to point it out.
Hi I get data from mongoDB and I try insert new data from other function. For some reason I get undefined.
What I'm doing is wrong and how can I fix it?
router.post("/list", (req, res, next) => {
const params = req.body;
var results_data = [];
Countability.find()
.populate("user")
.populate("company")
.populate("store")
.exec(function (err, data) {
_.forEach(data, function (value, key) {
results_data[key] = {
_id: value._id,
count: GetCount(10)
};
});
res.status(200).json({ status: 1, result: results_data });
});
});
const GetCount = (id) => {
DataRow.aggregate(
[
{
"$group": {
"_id": "$rowName",
"count": { "$sum": 1 }
}
}
]).exec((err,res) => {
var data = Promise.all([res]);
data.then(function (res) {
return res
})
})
}
Though the forEach has not finished,server starts sending response.
You need to make sure the results_data has got all data,then call res.status(200).json