聚合

分组

对 users 按 nameage 字段分组,并计算 age 的总和。

  1. package main
  2. import (
  3. "context"
  4. "<project>/ent"
  5. "<project>/ent/user"
  6. )
  7. func Do(ctx context.Context, client *ent.Client) {
  8. var v []struct {
  9. Name string `json:"name"`
  10. Age int `json:"age"`
  11. Sum int `json:"sum"`
  12. Count int `json:"count"`
  13. }
  14. err := client.User.Query().
  15. GroupBy(user.FieldName, user.FieldAge).
  16. Aggregate(ent.Count(), ent.Sum(user.FieldAge)).
  17. Scan(ctx, &v)
  18. }

按单个字段分组.

  1. package main
  2. import (
  3. "context"
  4. "<project>/ent"
  5. "<project>/ent/user"
  6. )
  7. func Do(ctx context.Context, client *ent.Client) {
  8. names, err := client.User.
  9. Query().
  10. GroupBy(user.FieldName).
  11. Strings(ctx)
  12. }

根据边进行分组

如果您想按照自己的逻辑进行聚合,可以使用自定义聚合函数。

下面展示了:如何根据用户的 idname 进行分组,并计算其宠物的平均 age

  1. package main
  2. import (
  3. "context"
  4. "log"
  5. "<project>/ent"
  6. "<project>/ent/pet"
  7. "<project>/ent/user"
  8. )
  9. func Do(ctx context.Context, client *ent.Client) {
  10. var users []struct {
  11. ID int
  12. Name string
  13. Average float64
  14. }
  15. err := client.User.Query().
  16. GroupBy(user.FieldID, user.FieldName).
  17. Aggregate(func(s *sql.Selector) string {
  18. t := sql.Table(pet.Table)
  19. s.Join(t).On(s.C(user.FieldID), t.C(pet.OwnerColumn))
  20. return sql.As(sql.Avg(t.C(pet.FieldAge)), "average")
  21. }).
  22. Scan(ctx, &users)
  23. }

Having + Group By

自定义 SQL 修饰符 可以帮助您控制所有查询。 下面展示了如何检索每个角色最老 (即 age 最大) 的用户。

  1. package main
  2. import (
  3. "context"
  4. "log"
  5. "entgo.io/ent/dialect/sql"
  6. "<project>/ent"
  7. "<project>/ent/user"
  8. )
  9. func Do(ctx context.Context, client *ent.Client) {
  10. var users []struct {
  11. Id Int
  12. Age Int
  13. Role string
  14. }
  15. err := client.User.Query().
  16. Modify(func(s *sql.Selector) {
  17. s.GroupBy(user.Role)
  18. s.Having(
  19. sql.EQ(
  20. user.FieldAge,
  21. sql.Raw(sql.Max(user.FieldAge)),
  22. ),
  23. )
  24. }).
  25. ScanX(ctx, &users)
  26. }

注意: The sql.Raw 至关重要。 It tells the predicate that sql.Max is not an argument.

上述代码会生成以下SQL查询:

  1. SELECT * FROM user GROUP BY user.role HAVING user.age = MAX(user.age)