Я использую uptrace/bun в качестве ORM для golang. Я объединяю таблицы с помощью метода .Relation(), но при объединении хочу ограничить результаты на основе условий. Например:
query := tx.NewSelect().
Model(xxxx).
Relation("B", func(sq *bun.SelectQuery) *bun.SelectQuery {
return sq.Where("accepted = True")
}).
Relation("C", func(sq *bun.SelectQuery) *bun.SelectQuery {
return sq
})
Дополнительные условия
...
...
Вышеуказанный Bun генерирует запрос, как показано ниже
select *
from a
left join b on a.id = b.a_id
left join c on b.id = c.b_id
where a.accepted = true
Дополнительные условия
...
...
...
Однако мне нужен следующий запрос
select *
from a
left join b on a.id = b.a_id and b.accepted = true
left join c on b.id = c.b_id
Дополнительные условия
...
...
...
Ответ
Чтобы решить проблему, связанную с использованием библиотеки uptrace/bun для ORM в Go, и выполнить соединение таблиц с дополнительными условиями для конкретной таблицы при использовании метода .Relation()
, вам нужно немного изменить подход к построению запроса. По умолчанию Bun применяет условия WHERE
, которые добавляются к основному запросу, в то время как вам необходимо включить условие непосредственно в выражение соединения.
Для достижения желаемого результата вы можете воспользоваться методом Join()
и указать условия соединения в его аргументах. Вот пример, как это можно сделать:
// Предположим, что у вас есть модели A, B и C, связанные между собой.
type A struct {
ID int
Accepted bool
B []B `bun:"rel:has-many"`
}
type B struct {
ID int
AID int
Accepted bool
C []C `bun:"rel:has-many"`
}
type C struct {
ID int
BID int
}
// Запрос с использованием Join для добавления условия в соединение.
query := tx.NewSelect().
Model((*A)(nil)).
Join("LEFT JOIN b ON a.id = b.a_id AND b.accepted = TRUE").
Join("LEFT JOIN c ON b.id = c.b_id").
Where("a.accepted = TRUE") // Дополнительные условия для A
// Другие условия
...
...
// Выполнение запроса
var results []A
err := query.Scan(&results)
if err != nil {
// обработка ошибки
}
В этом примере:
- Мы используем метод
Join()
для выполнения соединения с таблицей B и указываем условиеAND b.accepted = TRUE
прямо там, чтобы оно применялось к соединению. - После этого добавляем соединение с таблицей C так же как и прежде.
- Вы также можете присоединить любые дополнительные условия в
Where()
.
Таким образом, вы получите SQL-запрос, который выглядит следующим образом:
SELECT *
FROM a
LEFT JOIN b ON a.id = b.a_id AND b.accepted = TRUE
LEFT JOIN c ON b.id = c.b_id
WHERE a.accepted = TRUE
Этот подход позволяет вам более гибко управлять условиями соединения в вашем запросе к базе данных, что решает вашу исходную проблему.