Order By Function Akin To MySQL #7197
Replies: 4 comments
-
Here is my proposed implementation: await this.exampleDataRepo.find({
order: [{ func: 'IF ($:feesLocal:$ IS NULL, $:feesAbroad:$, $:feesLocal:$)'}]
}); The resulting query:
Fork: loopback-datasource-juggler: Fork: loopback-connector: |
Beta Was this translation helpful? Give feedback.
-
@raymondfeng @bajtos thoughts? |
Beta Was this translation helpful? Give feedback.
-
Thank you @shadyanwar for starting this discussion. I see how more advanced sorting criteria can be useful! At the moment, LB4 In other words, it is an array of property names with an optional ASC/DESC suffix. While your proposed format await this.exampleDataRepo.find({
order: 'IF ($:feesLocal:$ IS NULL, $:feesAbroad:$, $:feesLocal:$)'
}); Syntax aside, there is a big catch in our proposals. We cannot allow arbitrary Consider the following request:
Unless we implement strict validation of the SELECT * FROM Examples ORDER BY 1 LIMIT 0; SELECT * FROM users (I am not fluent in SQL these days, sorry if the query is not valid. I hope it does show the intent & the problem though.) |
Beta Was this translation helpful? Give feedback.
-
@bajtos Thanks for your thoughtful response. Regarding SQL injection, is there a way to prevent the filter from being used externally through the REST API and restrict it to only be used internally using the internally defined methods like find and findById only? |
Beta Was this translation helpful? Give feedback.
-
Suggestion
When querying data, most filters are customizable and flexible enough to get the desired results except for the
order
filter which is very limited to 'propertyName <ASC|DESC>
'. Powerful functions in MySQL or statements cannot be used.Use Cases
ORDER BY IF (`arg1` IS NULL, `arg2`, `arg1`)
ORDER BY ROUND(`arg`)
orORDER BY GREATEST(`arg1`, `arg2`)
ORDER BY `quantityOrdered` * `priceEach`
orORDER BY `arg`*2
Not being able to do any of this means having to loop through the results after fetching then doing some processing on them one by one.
Examples
One example is ordering results by more than one property. By default, when the first property is null, it comes up at the top when ordering ascendingly since NULL values are considered lower than any non-NULL values. Here are a few takes on Stackoverflow on the topic. This lingering issue also came up a few years ago in a Gitter discussion inside loopback community.
Here is an example where some products have prices for both local and abroad users while others have a price for only one of them:
MySQL:
SELECT ... ORDER BY `feesLocal` ASC, `feesAbroad` ASC
gives:Which is obviously different from the desired result. But the following:
MySQL:
SELECT ... ORDER BY IF (`feesLocal` IS NULL, `feesAbroad`, `feesLocal`)
gives:
Acceptance criteria
TBD - will be filled by the team.
Beta Was this translation helpful? Give feedback.
All reactions