Фильтрация в GoLang Bun при объединении таблиц через отношения

Вопросы и ответы

Я использую 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 {
    // обработка ошибки
}

В этом примере:

  1. Мы используем метод Join() для выполнения соединения с таблицей B и указываем условие AND b.accepted = TRUE прямо там, чтобы оно применялось к соединению.
  2. После этого добавляем соединение с таблицей C так же как и прежде.
  3. Вы также можете присоединить любые дополнительные условия в 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

Этот подход позволяет вам более гибко управлять условиями соединения в вашем запросе к базе данных, что решает вашу исходную проблему.

Оцените материал
Добавить комментарий

Капча загружается...