NSBatchInsertRequest and Relationship

Hi Everybody

I’ve a database composed by 3 entity:

Headword, Writing and Meaning

Relationship is one-to-many: One headword has many Writing and many Meaning.

Following the tutorial of Andrew Tetlaw @atetlaw about core data, I’ve used the nsbatchinserrequest to download the json, decoding and insert the objects in db.

making only the inserting all database composed by about 22000 records (I have 7300 headword, 7600 Meanings and 7400 Writings) is inserted in db in only 3 seconds. Very fast!!! but if after execution of batch insert request I try to set the relationship, all operation is done in 40 seconds.

I know that (and Andrew Tetlaw says so explicitly) with NSBatchInsertRequest you can’t set relationship. in fact, it throw an exception that it says that the objects are in different context.

But there is a fast way to manage the relationship?

This is the code that I’m using to do the insertion:

private func importJaappDB(from jaappJSON:JaappJSON) throws {
    guard let radicali = jaappJSON.radicali else { return }
    guard let kanji = jaappJSON.kanji else { return }
    guard let kunYomi = jaappJSON.kunYomi else { return }
    guard let onYomi = jaappJSON.onYomi else { return }
    guard let lemmi = jaappJSON.lemmi else { return }
    guard let scritture = jaappJSON.lemmaScrittura else { return }
    guard let significati = jaappJSON.lemmaSignificato else { return }
    
    var performError: Error?
    
    let taskContext = appDelegate.newTaskContext()
    
    taskContext.performAndWait {
        let radicalsBatchInsert = self.newBatchInsertRadicaliRequest(with: radicali)
        radicalsBatchInsert.resultType = .statusOnly
        
        let kanjiBatchInsert = self.newBatchInsertKanjiRequest(with: kanji)
        kanjiBatchInsert.resultType = .statusOnly
        
        let kunYomiBatchInsert = self.newBatchInsertKunYomiRequest(with: kunYomi)
        kunYomiBatchInsert.resultType = .statusOnly
        
        let onYomiBatchInsert = self.newBatchInsertOnYomiRequest(with: onYomi)
        onYomiBatchInsert.resultType = .statusOnly
        
        let lemmaBatchInsert = self.newBatchInsertLemmaRequest(with: lemmi)
        lemmaBatchInsert.resultType = .statusOnly
        
        let scritturaBatchInsert = self.newBatchInsertScritturaRequest(with: scritture)
        scritturaBatchInsert.resultType = .statusOnly
        
        let significatoBatchInsert = self.newBatchInsertSignificatoRequest(with: significati)
        significatoBatchInsert.resultType = .statusOnly
        
        do {
            let batchRadicalInsertResult = try taskContext.execute(radicalsBatchInsert) as? NSBatchInsertResult
            let batchInsertResult = try taskContext.execute(kanjiBatchInsert) as? NSBatchInsertResult
            let batchKunYomiInsertResult = try taskContext.execute(kunYomiBatchInsert) as? NSBatchInsertResult
            let batchOnYomiInsertResult = try taskContext.execute(onYomiBatchInsert) as? NSBatchInsertResult
            let batchLemmaInsertResult = try taskContext.execute(lemmaBatchInsert) as? NSBatchInsertResult
            let batchScritturaInsertResult = try taskContext.execute(scritturaBatchInsert) as? NSBatchInsertResult
            let batchSignificatoInsertResult = try taskContext.execute(significatoBatchInsert) as? NSBatchInsertResult
            
            let radicaliList = getRadicali()
            let kanjiList = getKanji()
            let kunYomiList = getKunYomi()
            let onYomiList = getOnYomi()
            let headwordList = getlemmi()
            let scritture = getScritture()
            let significati = getSignificati()
            
            for radicale in radicaliList {
                let kanjiRelazione = kanjiList.filter{($0.radicale?.contains(radicale.radicale!))!}
                radicale.addToKanji(NSSet(array: kanjiRelazione))
            }
            
            _ = kanjiList.map{$0.addToLettureKun(NSSet(array: kunYomiList.filter{($0.idKanji == $0.id)}))}
            _ = kanjiList.map{$0.addToLettureOn(NSSet(array: onYomiList.filter{($0.idKanji == $0.id)}))}
//                for kanji in kanjiList {
//                    let kunYomiRelationship = kunYomiList.filter{($0.idKanji == kanji.id)}
//                    let onYomiRelationship = onYomiList.filter{($0.idKanji == kanji.id)}
//                    kanji.addToLettureKun(NSSet(array: kunYomiRelationship))
//                    kanji.addToLettureOn(NSSet(array: onYomiRelationship))
//                }
            
            _ = lemmaList.map{ $0.addToScrittura(NSSet(array: scritture.filter{($0.idLemma == $0.id)}))}
            _ = lemmaList.map{ $0.addToSignificato(NSSet(array: significati.filter{($0.idLemma == $0.id)}))}
//                for lemma in lemmaList {
//                    let scrittureRelationship = scritture.filter{($0.idLemma == lemma.id)}
//                    let significatiRelationship = significati.filter{($0.idLemma == lemma.id)}
//                    lemma.addToScrittura(NSSet(array: scrittureRelationship))
//                    lemma.addToSignificato(NSSet(array: significatiRelationship))
//                }

            if let successRadical = batchRadicalInsertResult?.result as? Bool,
               let successKanji = batchInsertResult?.result as? Bool,
               let successKunYomi = batchKunYomiInsertResult?.result as? Bool,
               let successOnYomi = batchOnYomiInsertResult?.result as? Bool,
               let successLemmi = batchLemmaInsertResult?.result as? Bool,
               let successScritture = batchScritturaInsertResult?.result as? Bool,
               let successSignificati = batchSignificatoInsertResult?.result as? Bool,
               successRadical, successKanji, successKunYomi, successOnYomi, successLemmi, successScritture, successSignificati {
                try taskContext.save()
                DispatchQueue.main.async {
                    print("numero di radicali:\(self.getRadicali().count)")
                    print("numero di Kanji:\(self.getKanji().count)")
                    print("numero di KunYomi:\(self.getKunYomi().count)")
                    print("numero di OnYomi:\(self.getOnYomi().count)")
                    print("numero di Lemmi:\(self.getlemmi().count)")
                }
            }
            return
        } catch {
            performError = JaappError.batchInsertError
        }
        performError = JaappError.batchInsertError
    }
    
    if let error = performError {
        throw error
    }
}

if there is something you don’t understand, just ask.

thank you

This topic was automatically closed after 166 days. New replies are no longer allowed.