Filtering by relations
ant.Has filters rows by what they're related to, without loading anything. Each one becomes an EXISTS inside the same query, so it costs no extra round trip.
Has a related row
writers, err := db.Users.Where(ant.Has(&U.Posts)).All(ctx)
Add conditions on the related row.
drafting, err := db.Users.Where(ant.Has(&U.Posts, ant.Eq(&P.Published, false))).All(ctx)
Has none
silent, err := db.Users.Where(ant.HasNone(&U.Posts)).All(ctx)
HasNone with conditions matches rows with no related row that meets them.
The other direction
ant.HasOne follows a many-to-one or one-to-one relation.
byAdults, err := db.Posts.Where(ant.HasOne(&P.User, ant.Gt(&U.Age, 18))).All(ctx)
Combining
These are conditions like any other.
young, err := db.Users.Where(ant.Has(&U.Posts), ant.Lt(&U.Age, 18)).All(ctx)
same, err := db.Users.Where(ant.Not(ant.Has(&U.Posts))).Count(ctx)
They work on many-to-many and through relations too, and a global filter on the related model still applies.
Build it at run time
ant.Has needs the related model's configuration, which exists once a context has opened. Call it where the query is built, not in a package variable.
See it tested: tests/features/relations/has_test.go