I have a very simple one-to-many relationship between two models where a Trail
has many Coordinate
s. This relationship is configured with cascading deletes. However, when I delete a single Trail, I get N+1 delete queries.
@Model
final class Trail {
var name: String
var draft: Bool
var createdAt: Date
var startedAt: Date?
var endedAt: Date?
var notes: String
@Relationship(deleteRule: .cascade) var coordinates: [Coordinate] // <-- Relationship
init(name: String, coordinates: [Coordinate], draft: Bool = true, startedAt: Date? = nil, endedAt: Date? = nil) {
self.name = name
self.draft = draft
self.startedAt = startedAt
self.endedAt = endedAt
self.createdAt = Date.now
self.notes = ""
self.coordinates = coordinates
}
}
@Model
final class Coordinate {
var order: Int
var latitude: Double
var longitude: Double
var altitude: Double?
var recordedAt: Date?
var createdAt: Date
init(_ latitude: Double, _ longitude: Double, altitude: Double? = nil, recordedAt: Date? = nil, order: Int = 0) {
self.order = order
self.latitude = latitude
self.longitude = longitude
self.altitude = altitude
self.recordedAt = recordedAt
self.createdAt = Date.now
}
}
The delete code looks like this
func handleDeleteTrail(at offsets: IndexSet) {
offsets.forEach { offset in
modelContext.delete(filteredTrails[offset])
}
do {
try modelContext.save()
} catch let error {
Logger.main.error("Failed to delete trail(s) with error: (error)")
}
}
It’s actually 2(N+1) since it also creates individual inserts into the change history table for each operation.
Is there an easy way to optimize this? Why would SwiftData not do a batch delete by default?