How do I sanitize ILIKE query in Node-pg - javascript

I'm trying to create a filter for a findAll function that filters by name. The other filters in this function work fine but I can't get the name filter to work.
The function below accepts filter parameters (if any) and adds on to the WHERE query based on any passed in filters. Right now, when I pass in a name, it returns nothing unless the query matches a name in the database but I'm trying to return results that contain whatever the value of name is (i.e. a name query for 'net' would get you 'Neural Networks')
Here is what I have so far:
static async findAll(searchFilters = {}) {
let query = `SELECT handle, name, description, num_employees AS "numEmployees", logo_url AS "logoUrl"
FROM companies`;
let whereStatement = []
let values = []
const {name, minEmployees, maxEmployees} = searchFilters
if (minEmployees > maxEmployees) throw new BadRequestError('minEmployees cannot be greater than maxEmployees!')
if (!!minEmployees) {
values.push(minEmployees)
whereStatement.push(`num_employees >= $${values.length}`)
}
if (!!maxEmployees) {
values.push(maxEmployees)
whereStatement.push(`num_employees <= $${values.length}`)
}
if (!!name) {
values.push(name)
whereStatement.push(`name ILIKE $${values.length}`)
}
if (whereStatement.length > 0) {
query += ` WHERE ${whereStatement.join(" AND ")}`
}
query += ' ORDER BY name'
const companiesRes = await db.query(query, values)
return companiesRes.rows;
}
I tried typing it like this:
name ILIKE '%$${values.length}%'
but I got this message:
"error": {
"message": "bind message supplies 1 parameters, but prepared statement \"\" requires 0",
"status": 500
}
Is there a specific way to sanitize ILIKE queries in Node-pg or is my syntax just off?

I think your code in place where you append the name filter should look like:
...
if (!!name) {
values.push(`%${name}%`)
whereStatement.push(`name ILIKE $${values.length}`)
}
...
see 503#issuecomment-32055380

Related

Get one object of array Json

I followed this little how to to apply a simple api in nodejs. It is not quite my area of ​​expertise, I am a Computer Network Analyst and although I develop applications in C ++ (simple) and C #, I have a small doubt on how to obtain the result of an array returned by the following code:
Javascript Code using Mysql ->
//
exports.findAll = (req, res) => {
const name = req.query.name;
var condition = name ? { name: { [Op.like]: `%${name}%` } } : null;
Custumers.findAll({ where: condition })
.then(data => {
res.send(data);;
})
.catch(err => {
res.status(500).send({
message:
err.message || "Some error occurred while retrieving name."
});
});
};
Access to URL to check if everything goes as expected.
http://10.1.1.254:8085/api/custumers?name=Gabriel
My result:
[
{"id":6,
"name":"Gabriel",
"cod":10,
"igCustumer":"1",
"createdAt":null,
"updatedAt":null}
]
How could I get the values ​​of name, cod, imgCustumer?
Im try;
axios.get(`http://10.1.1.254:8085/api/custumers?name=Gabriel`).then((res) => {
let myvar = `My result:\n\n${res.data.name}`;
console.log(myvar);
})
Result if : Undefinid
You can access object values in JavaScript like this...
let res = [{"id":6,
"name":"Gabriel",
"cod":10,
"igCustumer":"1",
"createdAt":null,
"updatedAt":null}]
let name = res[0].name;
let cod = res[0].cod;
let igCustomer = res[0].igCustumer;
Because res is an array full of objects, you access an object with its location in the index, like res[0]. From there you can select the key/value pair in your object by using dot notation or brackets. Each method has its use.
Try something like this:
let res = [
{"id":6,
"name":"Gabriel",
"cod":10,
"igCustumer":"1",
"createdAt":null,
"updatedAt":null}
]
console.log(res[0]['name']);
console.log(res[0]['cod']);
console.log(res[0]['igCustumer']);
The problem with your code that you are trying to access a field that does not exists. The res.data will be equal to the response of your endpoint. Your response is an array, so apparently it does not have name field. So you need to take a particular object.
const user = res.data[0]; // Taking the first user.
Then you can access its data.
user.name; // Gabriel
To find data from array, you can iterate that array and use find like this :
let res = [
{id:6,
name:"Gabriel",
cod:10,
igCustumer:"1",
createdAt:null,
updatedAt:null}
]
let myVar = res.find((item) => {
return item.name === 'Gabriel'
});
console.log(myVar.name);
console.log(myVar.cod);
console.log(myVar.igCustumer);

How to put the item in DynamoDB with conditional expression that is not Primary Key

After generating a random uuid value I go ahead and assign it to the item.uuid:
let uuid = uuidv4();
let title = "Title 100"
let item = {
uuid: uuid,
title: title
};
With the Dynamodb table where the Primary Key is the item.uuid attribute, I add the item to the table with:
let TABLE_NAME = "My Table Name";
let options = {};
let promise = dbClient.put_item({ Item: item, TableName: TABLE_NAME, ...options });
The new item is inserted into the Dynamodb table with the Primary Key uuid generated earlier.
Next, I want to add another item to the same table, with the same "title 101" title:
let uuid = uuidv4();
let title = "title 101"
let item = {
uuid: uuid,
title: title
};
( both items will have the same title, but different uuid used as a Primary Key in a table).
Since I want to make sure, this item will be added only if no other items have the same "title 101" title, I use the ConditionExpression:
let options = {
ConditionExpression: "#title <> :title",
ExpressionAttributeNames: {
"#title": "title"
},
ExpressionAttributeValues: {
":title" : "title 101"
}
}
let promise = dbClient.put_item({ Item: item, TableName: TABLE_NAME, ...options });
promise
.then(res => {
console.log('--------- SUCCESS --------');
console.log(res);
console.log('-----------------');
});
But regardless of the ConditionExpression used here, the DynamoDB goes ahead and adds a new item with the same title value.
Is there a way to use the conditional expression on an attribute (field) that is not a Primary Key?
Condition Expressions are only applicable for update/delete(not for create), i.e if an item already exists for the given primary key(PartitionKey + HashKey), then checks the result of condition expression and proceeds if it returns true. We still need to pass entire Primary Key.
We can try something with scan + filter, but we will end up reading entire table to find a row matching a non keyed attribute, which is in efficient and will cost a fortune if table is big.
so, best thing in this case is adding a Global Secondary Index on title and run two separate queries, First query on GSI by title to determine if record exists with matching title and put-item if doesn't exist.

"Order by" results from SQLITE query not ordered

I am working on a webshop-project. I am trying to get sorted results based on parameter values from a sqlite database. I am trying to sort products based on "select" values.
In my app.js
app.get('/sortMaleProducts', function(request, response){
var sortValues = request.query.sortValue;
if(sortValues == 'priceASC')
{
sortValues = ["man", "price", "ASC"];
}
else if(sortValues == 'priceDESC')
{
sortValues = ["man", "price", "DESC"];
}
db.sortMaleProducts(sortValues, function(error, clothes){
if(error){
console.log("Error: "+ error);
}
else{
console.log(clothes)
const model = {
clothes
}
response.render("man.hbs", model)
}
})
})
In my db.js
exports.sortMaleProducts = function(sortValues, callback){
const query = 'SELECT * FROM products WHERE gender = ? Order by ?, ?'
db.all(query, sortValues, function(error, clothes){
console.log(clothes);
callback(error, clothes);
})
If I hardcode the query like:
const query = 'SELECT * FROM products WHERE gender = 'man' Order by price ASC'
Then it works....But I want to use user inputs so I can reuse code..
If you want to sort by a column, that column name has to appear directly in the query. What you're doing sorts the results by the strings 'price' and 'ASC', which are the same for every row so any order of results is sorted.
You can't use column names as parameters anywhere else in a query either, like in the columns to return or in a WHERE. They have to be present when the statement is prepared by compiling it into sqlite's internal bytecode, which happens before any parameter binding or the execution of the query.

Multiple wildcards via prepared statements for node.js mysql query

I have a JSON like this:
{"name":[{"tag":"Peter"}]}
And I'm dynamically building a prepared statement with multiple wildcards like this:
var sqlVar;
sqlVar += existParams.map(field => {
if (field === 'name') {
function getValues(item, index) {
var getVal = [item.tag];
return `${field} LIKE ?`;
}
return '('+name.map(getValues).join(' OR ')+')';
} else {
return `(${field} = ?)`
}
}).join(" AND ");
var sql = "SELECT * FROM names "+sqlVar+"";
connection.query(sql,
...
function getValues(item, index) {
var getVal = [item.tag];
return '%' + getVal + '%';
}
return name.map(getValues);
//Further attempts
//var getResult = name.map(getValues);
//return getResult.split(",");
//return name.map(getValues).join(', ');
, function(err, rows) {
...
});
If I have one value it works just fine. In console.log (SQL) I can see:
SELECT * FROM names WHERE (name LIKE ?)
BUT... if I have multiple values like:
{"name":[{"tag":"Peter"},{"tag":"Jack"}]}
I'm getting an SQL Error:
sql: 'SELECT * FROM names WHERE (name LIKE \'%Peter%\', \'%Jack%\' OR name LIKE ?) }
... So the second value is not going to the second position.
... but the result should be:
sql: 'SELECT * FROM names WHERE (name LIKE \'%Jack%\' OR name LIKE \'%Peter%\') }
... so in the console.log(sql):
SELECT * FROM names WHERE (name LIKE ? OR name LIKE ?)
What am I missing and how can I get the second value to the second LIKE and so on?!
Here is a similar example but with only one value: nodejs throws error with mysql like query via prepared statements
The only reason here for the resulting statement to be 'SELECT * FROM names WHERE (name LIKE \'%Peter%\', \'%Jack%\' OR name LIKE ?)
is that you have passed a nested array with value [['%Peter%', '%Jack%']] instead of a flat one.
Using the given object say,
const source = {"name":[{"tag":"Peter"}, {"tag":"Jack"}]}
Then the query values for the prepared statement should be
const queryValues = source.name.map(({tag}) => `%${tag}%`);
// [ '%Peter%', '%Jack%' ]
connect.query(sql, queryValues, (err, rows) => {
});

How can I access the 'results' object that is returned when running a Parse query?

I'm running a Parse query on all user objects (usersQuery), then querying for all MCI_Results objects that fulfill certain criteria (MCI_Results_Query).
Based on how many MCI_Results objects fulfill the criteria, I'm sending two different possible push notifications containing the searchTerm property of the that object as you can see below. When I attempt to run this code, it gives me an error stating:
Cannot read property 'searchTerm' of undefined
I'm assuming this is because results[0] itself is undefined, and that that's not the correct way to access the first object in results. How can I properly access it?
Code:
// For each user in the DB...
return usersQuery.each(function(user) {
// find all MCI_Results items with a newMatch of "YES" and a priority level of "High"
var MCI_Results = Parse.Object.extend("MCI_Results");
var MCI_Results_Query = new Parse.Query(MCI_Results);
MCI_Results_Query.equalTo('parent', user);
MCI_Results_Query.contains('newMatch', 'YES');
MCI_Results_Query.contains('itemPriority', 'High');
MCI_Results_Query.find()
.then(function(result) {
// Send a notification with the items name in it.
//
console.log('the MCI_Results_Query result is as follows:' + result);
// If >1 high priority items, say "New matches for _____ and X more items"
if (result.length > 1) {
var pushQuery = new Parse.Query(Parse.Installation);
pushQuery.containsAll("channels", [user.id, "highPush"]);
Parse.Push.send({
where: pushQuery, // Set our Installation query
data: {
alert: "New matches found for" + result[0].searchTerm + "and" + result.length-1 + "more items!"
}
});
}
// If 1 high priority item, say "New matches for _____!"
else if (result.length = 1) {
var pushQuery = new Parse.Query(Parse.Installation);
pushQuery.containsAll("channels", [user.id, "highPush"]);
Parse.Push.send({
where: pushQuery,
data: {
alert: "New matches found for" + result[0].searchTerm + "!"
}
});
} else {
// If no high priority items, don't send any push notification.
console.log('No high priority items fo u');
}
});
});

Categories