elixir - 使用 Ecto 选择、选择合并和连接
问题描述
我试图弄清楚如何组合选择和连接表,但遇到了问题。
假设我有表 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
},
]
}
]
解决方案
我会构建查询,预加载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()
未经测试,但它应该工作。
推荐阅读
- wordpress - WordPress:安装新插件不自动包含 Javascript 文件
- appium - Appium:原始错误:-[XCUIElement resolve]: unrecognized selector sent to instance
- python - 使用 Azure Datapreb 库与 Azure AD 服务主体连接 Azure SQL 数据库时出错
- ios - 如何在 Swift 中将 CIFilter 应用于视频而无需等待处理
- firebase - 我可以使用我不习惯登录的其他 js 文件从 firebase 中提取数据吗?
- javascript - 如何检查用户输入不大于小数?
- java - 在 Android Studio 上同步新项目时出现 Firebase 错误(ASCII 错误)
- azure-active-directory - 无法访问 /me/drive/root/children(也无法访问任何 driveItem 对象)
- android - 如何在房间迁移语句中使用 Kotlin 字符串模板
- validation - Salesforce - 验证规则 (RegEX)