-
-
Notifications
You must be signed in to change notification settings - Fork 3.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Bulk Update/Remove associations #6748
Comments
@jinzhu TL;DR: There's a bug in updating an object with associations. It doesn't set the object with the provided associations, but only adds new associations, so the preexisting associations don't get deleted (but they should). |
@jinzhu I've come across the same issue. Is this in your plans to be worked on and implemented? / Do you need any assistance? |
I expected nested associations to be replaced on update, but new duplicates are created |
1 |
1 similar comment
1 |
I've come across the same issue, I expected omitted keys on update to be deleted, but they are not. New associations can be created, and updated, but not deleted. I was almost about to switch to a different ORM, or just go with self made plain SQL queries. But I like the migrations and the struct to table generation in GORM so much, that I gave a workaround a try, the following is what i did. In order to work around the issue I updated my function with a map comparison before / after. Consider a library object, which contains a list of folders. Each folder has a foreign key to the library. This function will update the library and the associated folders, and delete any folders not in the update objects: func UpdateLibrary(library *models.Library) error {
// Fetch the current state of the library including associated folders
var currentLibrary models.Library
if err := db.Preload("Folders").First(¤tLibrary, library.ID).Error; err != nil {
return err
}
// Create a map of current folder IDs for quick lookup
currentFolderIDs := make(map[uint]bool)
for _, folder := range currentLibrary.Folders {
currentFolderIDs[folder.ID] = true
}
// Create a map of new folder IDs for quick lookup and to track seen folders
newFolderIDs := make(map[uint]bool)
for _, folder := range library.Folders {
newFolderIDs[folder.ID] = true
}
// Find folders to delete
for id := range currentFolderIDs {
if !newFolderIDs[id] {
// Folder is not in the new list, so delete it using Unscoped()
if err := db.Unscoped().Delete(&models.Folder{}, id).Error; err != nil {
return err
}
}
}
// Save the updated library with FullSaveAssociations
if err := db.Session(&gorm.Session{FullSaveAssociations: true}).Save(library).Error; err != nil {
return err
}
// Trigger notifications for logic that depends on instant update notifications
NotifyListeners(models.Notification{Type: "library_updated", Payload: library})
return nil
} With this change, it is able to update and remove associations... Not sure if this is the "correct" way to work around the issue, let me know :) |
There is a very simple solution to that. |
Your Question
My goal for what I am trying to accomplish, Replace database records with contents of input
This can either be delete/insert, range over each record and do db calls. Ideally I want to be able to do it all in bulk just receive said slice and update everything and all there associations (add/update/remove)
go.mod:
Sample of what would be considered the insert(doesn't exist yet in database), I would expect it to insert the employee with the 3 allowance codes (this part works). I use copier to copy the input xml model to the database model and use that as the input param for UpsertEmployees method.
Mapping from xml to database schema:
EmpID = ProcuraEmpID
If I were to then send the same EmpID record with modified allowance codes, I would expect to remove (I need hard delete, not soft delete). allowance code 3 as it's no longer present.
The relevant schema for reference, you can see I manually added the foreighKey/references gorm tags on the Employee AllowanceCodes
Original Gorm method which works when it comes to inserting and updating the main employee doc, it fails when removing attendance codes not present in the input
Research on gorm docs lead me to change it to this, which throws the following error
unsupported relations: EmployeeAllowance
being the gorm error itselfI also changed it to this to try replacing it all first, but I get the same relations error with this as well
The document you expected this should be explained
I've looked through all gorm docs at this point but the relevant ones
https://gorm.io/docs/has_many.html#Self-Referential-Has-Many
https://gorm.io/docs/associations.html#Association-Tags
https://gorm.io/docs/associations.html#Delete-Association-Record
Expected answer
The most database efficient way of updating a slice of employees and there associations with input, that includes inserts/updates/deletes(associations only, if no longer present in the input)
Asterisk on efficient as part of the reason for the rewrite is to improve database performance. If I'm able to just take the input and make the database reflect that all in one shot on the slice of employees that would be best. Otherwise I'm open to ranging the slices and doing database modifications on the element level if needed.
The text was updated successfully, but these errors were encountered: