【问题标题】:Using Ecto select, select_merge, and joins使用 Ecto 选择、选择合并和连接
【发布时间】:2019-08-29 13:47:16
【问题描述】:

我正在尝试弄清楚如何组合选择和连接表,但遇到了问题。

假设我有表 A、表 B 和表 C。表 A 有一些值,表 B 有很多表 C 中的项目。

我的查询是这样的:

query = from(
  a in TableA,
  select: %NewStruct{
    a: a.value  
  }
) 

from(
  a in query,
  join: b in TableB,
  on: b.a_id == a.id,
  join: c in TableC,
  on: c.b_id == b.id,
  select_merge: %{
    c: [c]
  }
)
|> Repo.all()

从某种意义上说,它会返回 3 个结构。它们都具有相同的值a,但c 是TableC 中的每一项。

当前结果:

[
  %NewStruct{
    a: "value"
    id: 1,
    c: %TableC{
      id: 1
    }
  },
  %NewStruct{
    a: "value"
    id: 1,
    c: %TableC{
      id: 2
    }
  },
  %NewStruct{
    a: "value"
    id: 1,
    c: %TableC{
      id: 3
    }
  }
]

通常,我知道使用preload: [c: c] 来让ecto 组合所有连接的项目,并嵌套在a.c 中。但我不能在这种情况下,因为NewStruct 只是一个defstruct。我尝试将NewStruct 转换为embedded_schema,但无法正确获取has_many 定义。

我的问题是:有没有办法告诉 Ecto 连接表 c 应该预加载/嵌套在 a.c 中?我知道,如果您执行SELECT * FROM a INNER JOIN c.b_id ON b.id 之类的操作,您将从 PSQL 获得 3 行的结果。但我确实知道,有时 Ecto 可以发挥一些作用,并且想知道我是否遗漏了什么。

想要的结果:

[
  %NewStruct{
    a: "value"
    id: 1,
    c: [
      %TableC{
        id: 1
      },
      %TableC{
        id: 2
      },
      %TableC{
        id: 3
      },
    ]
  }
]

【问题讨论】:

    标签: elixir ecto


    【解决方案1】:

    我会构建查询,预加载 TableC,然后才将 select 加载到结构中。

    TableA
    |> join(:left, [a], b in assoc(a, :table_b))
    |> join(:left, [b], c in assoc(b, :table_c))
    |> preload([b, c], [:table_b, table_c: c])
    |> select([a], %NewStruct{a: a.value, c: [c]})
    |> Repo.all()
    

    未经测试,但它应该可以工作。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-01-20
      • 2022-01-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-07
      • 1970-01-01
      相关资源
      最近更新 更多