-
-
Notifications
You must be signed in to change notification settings - Fork 4.1k
Add WhereHas and WhereDoesntHave helpers for relationship filtering #7642
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
base: master
Are you sure you want to change the base?
Conversation
|
Add Introduces first-class support for "exists / not-exists" style filtering on associations. New helper methods ( Key Changes• Created Affected Areas• This summary was automatically generated by @propel-code-bot |
| if len(inlineConds) > 0 { | ||
| existsQuery = existsQuery.Where(inlineConds[0], inlineConds[1:]...) | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[BestPractice]
Array bounds safety issue: applyConds assumes that if inlineConds has length > 0, it can safely access inlineConds[0] and pass the rest as variadic args. However, there's a subtle issue - if inlineConds has only one element, inlineConds[1:]... will be an empty slice, which is fine. But for better readability and explicit handling:
Suggested Change
| if len(inlineConds) > 0 { | |
| existsQuery = existsQuery.Where(inlineConds[0], inlineConds[1:]...) | |
| } | |
| if len(inlineConds) > 0 { | |
| if len(inlineConds) == 1 { | |
| existsQuery = existsQuery.Where(inlineConds[0]) | |
| } else { | |
| existsQuery = existsQuery.Where(inlineConds[0], inlineConds[1:]...) | |
| } | |
| } |
⚡ Committable suggestion
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.
Context for Agents
[**BestPractice**]
Array bounds safety issue: `applyConds` assumes that if `inlineConds` has length > 0, it can safely access `inlineConds[0]` and pass the rest as variadic args. However, there's a subtle issue - if `inlineConds` has only one element, `inlineConds[1:]...` will be an empty slice, which is fine. But for better readability and explicit handling:
<details>
<summary>Suggested Change</summary>
```suggestion
if len(inlineConds) > 0 {
if len(inlineConds) == 1 {
existsQuery = existsQuery.Where(inlineConds[0])
} else {
existsQuery = existsQuery.Where(inlineConds[0], inlineConds[1:]...)
}
}
```
⚡ **Committable suggestion**
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.
</details>
File: callbacks/where_has.go
Line: 192There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This part of the code is inspired by the code in the file callbacks/preload.go (line 288) and this code is correct, does not cause errors, and I think readability is better than the proposed version.
This PR covers #3871 feature request.
What did this pull request do?
This PR adds two new query helper methods —
WhereHasandWhereDoesntHave.These methods make it possible to filter query results based on related models, similar to how this is done in frameworks like Laravel Eloquent.
Problem
Currently, GORM lacks convenient methods for filtering records by the existence (or absence) of related entities.
For example, there is no built-in way to express queries like:
or the inverse case using WhereDoesntHave.
As a result, developers must write verbose raw joins or subqueries, which reduces readability and reusability.
Solution
This PR introduces:
Filters parent records that have related models matching the scope.
Filters parent records that do not have related models matching the scope.
These methods apply only to query building (e.g., SELECT) and do not affect update/insert logic.
Implementation notes
User Case Description
Assume the following model structure:
1. Basic WhereHas
Find all users who have pets:
2. Basic WhereDoesntHave
Find all users who don’t have pets:
3. Conditional WhereHas
Find all users who have toys of a specific type:
4. Nested WhereHas
Find all users who have pets without toys: