-
Notifications
You must be signed in to change notification settings - Fork 228
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
Many to Many relation query filtering issue #1822
Comments
I understand the issue. It looks a lot like https://vladmihalcea.com/sql-query-parent-rows-all-children-match-filtering-criteria/. To answer your questions, Elide does not support this kind of filter today in the database. Generating the JPQL in a general way for this kind of query seems like it could be tricky. Another alternative might be to evaluate part of the filter expression in memory - possibly leveraging the logic Elide uses to evaluate filter expressions on computed fields ( As a workaround/test, try adding another computed attribute to the Tag model that just mirrors/returns the ID field. Then change the client filter replacing tag.id with the computed field instead. If you are worried about the performance of this, it should be possible to filter by at least one of the IDs in the database either by:
Let me know if you try the workaround above or have questions. |
The above workarounds solves to some extend, but not as a complete solution. Some concerns of this solution
It will be great, if SQL formation can be controlled by Elide itself which will be a complete solution. Let me know, if Elide any plan to look into this ? |
I've spent some time looking at this and have a few thoughts:
I tried the following workaround today on Elide 5 with the following caveats:
Here is my example query. Note that the filter is on the relationship instead of the relationship ID: I registered a custom FilterTranslator.registerJPQLGenerator(Operator.IN, new ClassType(Book.class), "authors", (columnAlias, params) -> {
String param = params.get(0).getPlaceholder();
return String.format("EXISTS (SELECT 1 FROM Author a WHERE a.id = example_Book_authors.id AND a.id = %s)", param);
}); This fragment will run a separate EXISTS subquery for each filter predicate in the expression. The table alias (example_Book_authors) is generated by Elide from the full class name (example.Book) and the relationship (authors). Note that the example doesn't generate a correct expression for multiple parameters (that is easy to fix, but this is just a test/example). In short, I think we can fix Elide 5 (elide 4 would require a contract change) with a similar approach that will work in the general case (without having to register a JPQL fragment generator). Let me know if this workaround unblocks you. |
Appreciate for the understanding and quick PRs... There is a concern, May be, EXISTS cannot solve this issue, We need the result as -- "All books which has BOTH tag1 AND tag2" Generated SQL should be like -- (in case of 2 tag condition) SQL level can solve only by "groupBy() and Having() clauses" |
The latest PR should address the issue. See one of the tests below.
{
"data": [
{
"type": "book",
"id": "1",
"attributes": {
"awards": [
"National Book Award",
"Booker Prize"
],
"chapterCount": 0,
"editorName": null,
"genre": "Literary Fiction",
"language": "English",
"publishDate": 0,
"title": "The Old Man and the Sea"
},
"relationships": {
"authors": {
"data": [
{
"type": "author",
"id": "1"
},
{
"type": "author",
"id": "2"
}
]
},
"chapters": {
"data": [
]
},
"editor": {
"data": {
"type": "editor",
"id": "1"
}
},
"publisher": {
"data": {
"type": "publisher",
"id": "1"
}
}
}
}
]
} |
A use case is explained below, when implemented using Elide/ (may be ORM issue), the filtering is not working as expected.
Scenario is,
The DB design is as follows,
Query formed using elide is as follows
GET /api/v1/books?filter=tags.id==comic;tags.id==newReleases
The resulting query created is
select distinct book0_.id as id1_0_ from book book0_ left outer join book_tag tag1_ on book0_.id=tag1_.book_id left outer join tag tag2_ on tag1_.tag_id=tag2_.id where (lower(tag2_.id) in (lower(?))) and (lower(tag2_.id) in (lower(?))) limit ?
This query will never satisfy, as the SQL search in the same row with different Id.
The actual query to be formed should be based on "groupby() having count() = X"
Question:
The text was updated successfully, but these errors were encountered: