I am using node.js and trying to query based on multiple filters if only they are true
select * from orders ${isFilter ? 'where' : ''}
${orderId !== undefined && orderId ? `order_id = '${orderId}' or ` : '' }
${receiptId !== undefined && receiptId? `receipt_id = '${receiptId}' or `: '' }
${driver !== undefined && driver ? `driver_id = '${Number(driver)}'` : '' }
this works fine where there is no filter or when all the filters are true but the OR causes an issue when one filter or more are missing. what would be the best way to handle this ?
This is a pseudo code to dynamically compose the query
var clause = 'where';
var query = 'select * from orders';
if (isFilter) { // this statement could be removed
if (orderId !== undefined && orderId) {
query += clause + ' order_id = `${orderId}`';
clause = 'or';
}
if (receiptId !== undefined && receiptId) {
query += clause + ' receiptId = `${receiptId}`';
clause = 'or';
}
if (driver !== undefined && driver) {
query += clause + ' driver = `${driver}`';
clause = 'or'; // this is not really needed, but it could be useful for further filters in future
}
}
let whereClause = [];
if(orderId) whereClause.push(`order_id = '${orderId}'`);
if(receiptId) whereClause.push(`receipt_id = '${receiptId}'`);
if(driver) whereClause.push(`driver_id = ${parseInt(driver)}`);
let whereQuery = whereClause.join(' OR ');
let sql = `select * from orders where true ${whereClause.length ? whereQuery : ''}`;
try using join. so that you can add many properties even not in order. Also if you're expecting it to be undefined, then you may remove that as it resulted false on condition statement.
I think it would be reasonable if you can log the query. we can be sure about the query that's being sent.
This would be the first step to troubleshoot and may be we can use the way you are trying using ternary operator with few changes.
The code you used above to build the query string is not possible to cover all possible cases.
Example:
What if isFilter==false and one of the 3 variables orderId, receiptId and driver has the value !== undefined? => your query will be wrong because the WHERE statement is missing.
Another case, if one of the variables orderId or receiptId satisfied the condition and the variable driver is not valid. => Your query will be wrong because of the extra of 'OR' at the end.
Those are the 2 cases that are most likely to cause problems for the above code. Here is my suggestion to solve your problem:
queryString="select * from orders"
if(isFilter){
queryString+=' where'
if(orderId){
queryString+=' ..... or'
}
if(receiptId){
queryString+=' ..... or'
}
if(driver){
queryString+=' .....'
}
}
queryString=queryString.trim()
if(queryString.endsWith('or')){
queryString=queryString.substring(0,queryString.length-2)
}
if(queryString.endsWith('where')){
queryString=queryString.substring(0,queryString.length-5)
}
select * from orders ${isFilter ? 'where 1=0' : ''}
${orderId !== undefined && orderId ? `OR order_id = '${orderId}' ` : '' }
${receiptId !== undefined && receiptId? `OR receipt_id = '${receiptId}' `: '' }
${driver !== undefined && driver ? `OR driver_id = '${Number(driver)}'` : '' }
Instead if its AND you can do 1=1 instead of 1=0.
Related
I have two variables, search and selectedAsset. When Search or selectedAsset is shown I would like to set a new variable named optionalparamaters which excutes when search is true or selectedAsset is true. I am trying to pass the optioinalParamaters variable into the url param depending on its case.
let optionalSearch = search === '' ? '' : `?asset_type=${search}`
let optionalSelectedAsset = selectedAsset === '' ? '' : `?asset_type=${selectedAsset}`
let results = await verifiedGet(`get_all_reviews/${(currentPage - 1) * resPerPage}/${resPerPage}${optionalSearch}`, user.user)
Right now obviously you can see that the optionalSearch is only being called, hence why I wanted to create that new variable optionalParamaters which I can pass through based on whether the condition is sett to search or selectedAsset.
Updated code:
let optionalParams = search === '' ? '' : `?asset_type=${search}` : (selectedAsset === '' ? '' : `?asset_type=${selectedAsset}` )
This is a solution very readable without ternary.
const params = new URLSearchParams();
params.set('resPerPage', resPerPage);
if ( !!search ) {
params.set('asset_type', search);
params.set('optionalSearch', true);
}
if ( !!selectedAsset ) {
params.set('asset_type', selectedAsset);
params.set('optionalSearch', true);
}
const url = `/${(currentPage - 1) * resPerPage}/?${params.toString()`;
let results = await verifiedGet(url, user.user);
searchList(array, filters) {
var currentUserId = 125;
var list = array;
// array example [{aisle: A9, userid: 125},{aisle: B2, userid: null},{aisle: C#, userid: 125}]
// filters example {assignedButtonActive: true, unassignedButtonActive: false, aisle: A9}
result = Object.keys(list)
.map((key) => {
return { ...list[key] };
})
.filter((data) => {
// If assigned or unassigned buttons are not active, this filter doesnt apply and aisle should be the only thing filtering
let assigned = filters.assignedButtonActive
let unassigned = filters.unassignedButtonActive
let aisleSelection = filter.aisle;
let aisle = data.aisle;
let userid = data.userid;
return aisle.indexOf(aisleSelection) > -1 // Need a conditional to also filter out assigned/unassigned if the buttons are active, otherwise not needed.
});
return result;
}
I am trying to filter a list with the combination of an input search and button/flags. I have no problem with the input search function filtering and returning the list. The problem Im having is using boolean flags along with the search input to be even more exact on what i want to filter, but I am having an issue on how to return the result using conditionals/booleans in this case. I cant seem to mix the two conditions for a return with both filters applied. I've tried something like this return aisle.indexOf(aisleSelection) > -1 && (assigned) ? assignedTo == currentUserId : (unassigned) ? assignedTo == null : [] but seems I'm way off. For example if either assigned/unassigned flags are active, it will add one of these two filters assignedTo === currentUserId or assignedTo == null to filter along with aisle filter as well, pretty much so they can work together as well, not one or the other
Not looking for the solution written out for me, more on how I can handle this filtering beyond just an input, with the possibility to off more filters being used
Any help/tips would be greatly appreciated
Finish out the function before returning, then have different return statements for each condition
rather than
return aisle.indexOf(aisleSelection) > -1
try
if (aisle.indexOf(aisleSelection) > -1) {
return true}
else if (other possibility){
return true}
else (case to filter out){
return false}
filter gets called on each element in the array, and decides to keep the element if the callback function returns true
Based on what I have understood, follow through this code especially the part I have commented then let me know if this what you wanted. If there's you don't get, let me know.
function searchList(array, filters) {
var currentUserId = 125;
var list = array;
result = Object.keys(list)
.map((key) => ({ ...list[key] }))
.filter((data) => {
let assignedSelection = filters.assignedButtonActive;
let unassignedSelection = filters.unassignedButtonActive;
let aisleSelection = filters.aisle;
let aisle = data.aisle;
let userid = data.userid;
return Boolean(Boolean(assignedSelection) || Boolean(unassignedSelection)) && aisle.includes(aisleSelection)?assignedTo = currentUserId:assignedTo = null;
/**
Explanation:
I am not sure of what you wanted to achieve with this, but follow through and see If this is what you wanted.
1. Boolean(Boolean(assignedSelection) || Boolean(unassignedSelection))
This part will return true if either assignedSelection or unassignedSelection is true.
This part will return false if both assignedSelection and unassignedSelection are false.
2. aisle.includes(aisleSelection)
This part will return true if aisleSelection matches aisle
This part will return false if aisleSelection does not match aisle
3. Boolean(Boolean(assignedSelection) || Boolean(unassignedSelection)) && aisle.includes(aisleSelection)
This part will return true if both part_(1) and part_(2) return true
Thus part will return false if either part_(1) or part_(2) returns false
4. return Boolean(Boolean(assignedSelection) || Boolean(unassignedSelection)) && aisle.includes(aisleSelection)? assignedTo = currentUserId : assignedTo = null;
This part will return null if part_(3) returns false
This part will give the variable assignedTo the value currentUserId if part_(3) returns true
*/
});
return result;
}
//Execute the example
var arrayExample = [
{ aisle: "A9", userid: 125 },
{ aisle: "B2", userid: null },
{ aisle: "C#", userid: 126 },
];
var filtersExample = {
assignedButtonActive: true,
unassignedButtonActive: false,
aisle: "A9",
};
searchList(arrayExample, filtersExample);
in such cases, I use the usual brackets to show the individual parts of the inequality. example
return aisle.indexOf(aisleSelection) > -1 && (assigned) ? assignedTo == currentUserId : ((unassigned) ? assignedTo == null : [])
but maybe
return assignedTo = (aisle.indexOf(aisleSelection) > -1 && (assigned) ? currentUserId : ((unassigned) ? null : []))
I may have misunderstood the necessary conditions. if you describe the conditions in more detail, the answer will be more correct.
I've got probelm with filtering array from form values.
I using angular 7 and express js
export function getItems(req: Request, res: Response) {
const itemCriteria: ItemCriteria = req.body.itemCriteria;
const name = (itemCriteria.name) ? itemCriteria.name : '';
const description= (itemCriteria.description) ?
itemCriteria.description: '';
const category= itemCriteria.category;
const filterItems: Item[] = items
.filter(item=> item.category.id === category &&
item.name .includes(name ) &&
item.description.includes(description)
);
res.status(200).json(filterItems);
}
When I fill all fields filterItems is correct, but when I fill only one or two fields I've got error 'Cannot read property of undefinied'. This fields is from reactive form but only one is required else is optional. So my question is how can I filter this array correct?
When one of Criteria is empty, you don't have to include it in the filter function.
So you can change it by following.
const filterItems: Item[] = items
.filter(item=> (!category || (item.category && item.category.id === category)) &&
(!name || (item.name && item.name.includes(name))) &&
(!description || (item.description && item.description.includes(description))
);
You are trying to read a property of an undefined variable. It's hard to know which one it is, but you can protect your code from these types of errors by making sure a variable is defined like this:
const myProperty = someVariable && someVariable.someProperty
This shortcircuits if someVariable is falsy.
In your case this might look like:
const filterItems: Item[] = items
.filter(item=> item && item.category && item.category.id === category &&
item.name && item.name.includes(firstName) &&
item.description && item.description.includes(lastName)
);
(also it's not clear where firstName, lastName, and items come from, but I don't think that's the cause of the error you're asking about)
Instead of if...else statement how to do using ternary operation or any alternative way to simplify code in javascript
if(req.query.pr=="trans"){
util.transUrl(req.originalUrl).then(param => {
res.redirect(param);
})
}
else if(req.query.pr=="inst"){
util.instaUrl(req.originalUrl).then(param => {
res.redirect(param);
})
}
else{
res.status(400).send("Contact the editor of the originating page.")
}
There are multiple ways to write a conditional statement in JS. However, if there are multiple statements I would say you should stick to if else if else. But if you want to see other approaches, here they are:
Using Ternary operator ? :
const {pr} = req.query
pr === 'trans'
? util.transUrl(req.originalUrl).then(param =>
res.redirect(param)
)
: pr === 'inst'
? util.instaUrl(req.originalUrl).then(param =>
res.redirect(param)
)
: res.status(400).send('Contact the editor of the originating page.')
Using Gate logic && ||
const {pr} = req.query
(pr === 'trans' &&
util.transUrl(req.originalUrl).then(param =>
res.redirect(param))
) ||
(pr=== 'inst' &&
util.instaUrl(req.originalUrl).then(param =>
res.redirect(param))
) ||
res.status(400).send('Contact the editor of the originating page.')
Now, Looking at your code, here if and else if statements are similar. So you can avoid else if using ternary operator like this:
const {pr} = req.query
if(pr === 'trans' || pr === 'inst'){
util[pr === 'trans' ? 'transUrl' : 'instaUrl'](req.originalUrl)
.then(param => res.redirect(param))
}
else{
res.status(400).send('Contact the editor of the originating page.')
}
Just one FYI: Please consider using === instead of == whenever you are comparing strings and there is no need of coercion.
I am using Dexie.JS to work with IndexedDB.
Currently, have a stupid query written as:
return db.events.each((element) => {
let d = element.cause.data;
if (d.hasOwnProperty('deleted') && (false == d.deleted) &&
d.hasOwnProperty('abbreviation') &&
d.hasOwnProperty('contents') && (d.abbreviation == key)) {
snippet = d.contents;
}
}).then(() => {
return snippet;
});
It is working correctly, but slow as molasses on a large database. Should I run each on a collection made from db.events with applied where? Would that improve performance?
Thank you
Yes if assuming your "key" variable is of an indexable type: string, number, Date, TypedArray or Array, you can optimize the query like this:
First, make sure to add the index "cause.data.abbreviation" on db.events:
db.version(2).stores({
events: 'yourPrimaryKey, cause.data.abbreviation'
});
Then, rewrite the query like this:
return db.events
// Let indexedDB sort out all items matching given key:
.where('cause.data.abbreviation').equals(key)
// Filter the rest manually using Collection.filter():
.filter(element => {
let d = element.cause.data;
return (d.hasOwnProperty('deleted') && (false == d.deleted) &&
d.hasOwnProperty('contents'));
})
// Execute the query and only return the first match:
.first();