JOIN 查询

当 `include` 不足以表达查询需求时,可用 `linq!` 宏的 `inner_join` / `left_join` 子句手动 JOIN。字符串 API(`inner_join("t", "a", "b")` 等)已移除。

INNER JOIN

// 多参数闭包:|a: T1, b: T2| a.col == b.col
let results = linq!(ctx.set::<Blog>();
    inner_join |a: Blog, b: Post| a.blog_id == b.blog_id
).to_list().await?;

// 配合过滤
let rust_posts = linq!(ctx.set::<Blog>();
    inner_join |a: Blog, b: Post| a.blog_id == b.blog_id;
    // 后续可加其他子句
).to_list().await?;

LEFT JOIN

// 保留左表所有行,右表无匹配则为 NULL
let results = linq!(ctx.set::<Blog>();
    left_join |a: Blog, b: Post| a.blog_id == b.blog_id
).to_list().await?;

JOIN 后的实体物化

手动 JOIN 时,`to_list()` 仍按主实体类型物化。关联数据不会自动填充到导航属性中。如需完整的关系数据,仍推荐使用 `include` 子句:

// 用 include 自动物化导航(推荐)
let blogs = linq!(ctx.set::<Blog>(); include b.posts).to_list().await?;

// 用 join 做跨表过滤(手动物化)
let blogs = linq!(ctx.set::<Blog>();
    inner_join |a: Blog, b: Post| a.blog_id == b.blog_id;
).to_list().await?;

设计要点

| 实践 | 说明 | |------|------| | 优先用 `include` | 关系数据物化自动化,代码更少 | | JOIN 用于筛选条件 | 当需要根据关联表字段过滤主表时,JOIN 比子查询更直观 | | 多参数闭包须标注类型 | `|a: Blog, b: Post|` 不能省略类型 |

下一节:[全局查询过滤器](global-query-filters.md)