0

I'm inserting hundreds of thousands of objects using NSBatchInsert, now i want to add relationships between objects (let say A and B, with 1-to-many relationship) as no batch operation supports relationship i will need to use the most efficient and fast way to achieve what I want, the best way I could think of is to use "GroupBy" to fetch object, but this will lead to start a loop to fetch the A entity (as the Key of the Dictionary will be a property not an object).

is there any way to have a Dictionary as fetch result having as Key an NSManagedObject (the A object) and the value an Array of NSManagedObject (B objects) ?

-> let result: [A: [B]]

Thank you

5
  • 1
    Anything that involves fetching all batch inserted records at once and not even as faults defeats the purpose of using a batch insert. Think about dividing your problem into smaller pieces and fetch a group, establish relationship and continue with the next group. Commented Dec 4, 2024 at 11:04
  • This is what i did using Swift concurrency using TaskGroup, It was a success (from 1 minute to 35 seconds) but still, it takes too long. What i want is to let CoreData take care of grouping B objects by A objects, so i will not have to fetch Bs when looping into As. And yes, objects are in fault mode (this is the default state when fetching). Commented Dec 4, 2024 at 12:57
  • How does B know that it belongs to A or vice versa before the relationship is established? You need to provide more information to elaborate the options you might have. Commented Dec 4, 2024 at 13:53
  • B have the A id it belongs to. Commented Dec 4, 2024 at 17:57
  • @RedMak what are you going to do with result [A: [B]]? is it for creating relationships? Commented Dec 7, 2024 at 5:14

1 Answer 1

-1

A dictionary of [A: [B]] efficiently, where A is an NSManagedObject representing the parent entity and [B] is an array of related objects, you’ll need a solution that minimizes looping and fetches while working with Core Data.

Approach 1: Fetch A Entities and Use NSManagedObject Relationships

// Assume we have a managed object context `context` let fetchRequest: NSFetchRequest<A> = A.fetchRequest() do { let aObjects = try context.fetch(fetchRequest) var result: [A: [B]] = [:] for a in aObjects { if let bObjects = a.bRelation?.allObjects as? [B] { result[a] = bObjects } } // Now `result` contains the grouped dictionary } catch { print("Failed to fetch A entities: \(error)") } 

Core Data automatically manages the relationship, so accessing a.bRelation fetches related objects lazily (or eagerly if configured with a Fetch Request for preloading).

Approach 2: Use a Fetch Request with NSDictionaryResultType

let fetchRequest = NSFetchRequest<NSDictionary>(entityName: "B") fetchRequest.resultType = .dictionaryResultType // Assuming "aProperty" is the property that links B to A fetchRequest.propertiesToFetch = ["aProperty"] fetchRequest.propertiesToGroupBy = ["aProperty"] do { let groupedResults = try context.fetch(fetchRequest) var result: [A: [B]] = [:] for group in groupedResults { if let aObject = group["aProperty"] as? A { let bFetchRequest: NSFetchRequest<B> = B.fetchRequest() bFetchRequest.predicate = NSPredicate(format: "aProperty == %@", aObject) let bObjects = try context.fetch(bFetchRequest) result[aObject] = bObjects } } // `result` now contains the grouped dictionary } catch { print("Failed to group and fetch: \(error)") } 

NSDictionaryResultType allows you to group objects in the database query itself, reducing the in-memory operation overhead.

Approach 3: Batch Fetch and Process Relationships

let batchSize = 500 // Fetch all B objects in batches let fetchRequest: NSFetchRequest<B> = B.fetchRequest() fetchRequest.fetchBatchSize = batchSize do { let bObjects = try context.fetch(fetchRequest) var result: [A: [B]] = [:] for b in bObjects { if let a = b.aRelation { // Assuming `aRelation` is the to-one relationship to A if result[a] == nil { result[a] = [] } result[a]?.append(b) } } // `result` now contains the grouped dictionary } catch { print("Failed to fetch B entities: \(error)") } 
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.