Your Question

I have two models lets it'll be Book and Author

type Book struct {
  ID uint
  Title string
  Year uint
  Authors []*Author `gorm:"many2many:books_authors"`
}

type Author struct {
  ID uint
  Name string
  Birthday time.Time
}

and created object:

book := Book{
  ID: 1,
  Title: "It",
  Authors: []Author{
    Author{ID: 1},
    Author{ID: 3},
  }

I want to: - Update Book.Title to the new string - Replace Authors to authors with IDs 1, 3 (previously this book has authors with IDs 1, 2). - Return &book with fully filled associations structs (at least names)

Is it possible to do in one statement?

Now I have two statements in transaction:

        err = db.Transaction(func(tx *gorm.DB) error {
        err = tx.WithContext(ctx).
            Updates(&book).
            Error
        if err != nil {
            return err
        }

        err = tx.WithContext(ctx).
            Model(&book).
            Association("Authors").
            Replace(book.Authors)
        if err != nil {
            return err
        }

        return nil
    })

but update and replace actions generate duplicate queries:

INSERT INTO "authors" ("name","id") VALUES ('',1),('',3) ON CONFLICT DO NOTHING RETURNING "id"
INSERT INTO "books_authors" ("book_id","author_id") VALUES (1,1),(1,3) ON CONFLICT DO NOTHING

else returning filled authors doesn't work at all!

The document you expected this should be explained

I have read documentation Association Mode

Expected answer

I need an assist to rewrite my statments to avoid duplication queries and achieve my goals. Could you help me, please?