-
Notifications
You must be signed in to change notification settings - Fork 36
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ActiveRecordFilterQueryBuilder
can't deal with "conjunction of relations"
#404
Comments
Solution: Query Builder Uses Multiple JoinsIt's theoretically possible for the query builder to spot cases like this and, instead of doing a single join, joining the I'm not sure of the level of effort required. |
Solution: Resource-Level FiltersSince Praxis filters always translate to a SQL query constraint, they are enormously efficient. However, not every interesting filter predicate can be applied in pure SQL. One option is to expose a second level of filtering which gets applied "in the resource plane," after the DB models are loaded and transformed into resources. Essentially, this filtering would happen either in a Resource getter-proxy method, or it would happen very late in the request lifecycle e.g. during This could become inefficient if used with huge result sets, because the filtering would need to be done in pure Ruby. Likewise, it might be tricky to write the Ruby code (and respect things like the user's chosen filtering operator, the comparison value, etc). However, it has the advantage of being tremendously powerful; I can filter resource collections by literally any Ruby predicate that I can write. If used with care to handle corner cases that the DB can't handle, this could solve the problem at hand neatly and elegantly, and make Praxis filtering much more powerful. |
Another manifestation of this problem is negation. You cannot ask for widgets w/o a specific tag. Naturally, I want to say Another issue that we are experiencing is with very complex filter logic. An example would be when you want to count an association and compare the number against an integer. For all these issues, we have come up with a general solution in our code that partially goes around praxis filtering. We traverse the filter tree down to its leaf nodes. Process each leaf node, and use the filter tree to merge the results. This approach makes one MySQL query for each leaf node, which can have performance implications. However, the benefits outways for us.
This is how our solution works:
Here is a little visual we made to communicate internally: We would love your input on our approach first and foremost. We were also hoping to hear if there is any interest in solving the issues in praxis. It could be in any shape from Praxis core functionality, to a configurable path. We are more than happy to contribute in any form. |
Problem Statement
Given a structure like the following:
When I want to filter for "widgets that have tags A and B," the natural inclination is to define a filter on
tags
forwidgets#index
, so that in my filter parameter, I can say things like:However, the query builder generates a nonsensical query in this case. It joins
tags
a single time and addswhere({tags: {nam: 'A'}}).where({tags: {name: 'B'}})
clause -- which is to say, it looks for a single row oftags
whose name is simultaneously A and B.The purpose of this issue is to discuss potential solutions to this problem (which we may not necessarily consider a bug, but which is an impediment to anyone who wants to filter by conjunction-of-relations.)
The text was updated successfully, but these errors were encountered: