10

विकास के तहत हमारे ऐप में हम अपने डेटा को स्टोर करने के लिए एक स्क्लाइट बैकिंग स्टोर के साथ कोर डेटा का उपयोग कर रहे हैं। हमारे ऐप के लिए ऑब्जेक्ट मॉडल जटिल है। साथ ही, हमारे ऐप द्वारा प्रदत्त डेटा की कुल मात्रा आईओएस (आईफोन/आईपैड/आईपॉड टच) ऐप बंडल में फिट होने के लिए बहुत बड़ी है। इस तथ्य के कारण कि हमारे उपयोगकर्ता आमतौर पर डेटा के सबसेट में रूचि रखते हैं, हमने अपने डेटा को इस तरह से विभाजित किया है कि ऐप जहाजों में डेटा ऑब्जेक्ट्स के सबसेट (यद्यपि, ~ 100 एमबी) के साथ जहाज करता है ऐप बंडल आईट्यून इन-ऐप खरीद के माध्यम से अतिरिक्त सामग्री के लिए भुगतान करने के बाद हमारे उपयोगकर्ताओं के पास हमारे सर्वर से अतिरिक्त डेटा ऑब्जेक्ट्स (आकार ~ 5 एमबी से 100 एमबी) डाउनलोड करने का विकल्प होता है। वृद्धिशील डेटा फ़ाइलें (स्क्लाइट बैकिंग स्टोर्स में मौजूद) उसी xcdatamodel संस्करण का उपयोग उस डेटा के रूप में करती है जो बंडल के साथ जहाज़ करता है; ऑब्जेक्ट मॉडल में शून्य परिवर्तन हैं। वृद्धिशील डेटा फ़ाइलों को हमारे सर्वर से gzipped sqlite फ़ाइलों के रूप में डाउनलोड किया जाता है। हम ऐप के साथ बढ़ती सामग्री को शिपिंग करके हमारे ऐप बंडल को फूट नहीं करना चाहते हैं। साथ ही, हम webservice (जटिल डेटा मॉडल की वजह से) पर प्रश्नों पर भरोसा नहीं करना चाहते हैं। हमने अपने सर्वर से incremental sqlite डेटा के डाउनलोड का परीक्षण किया है। हम डाउनलोड किए गए डेटा स्टोर को ऐप के साझा किए गए लगातारस्टोरकॉर्डिनेटर में जोड़ने में सक्षम हैं। दो आईओएस कोर डेटा निरंतर स्टोर मर्ज करने का एक प्रभावी तरीका क्या है?

{ 
       NSError *error = nil; 
       NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys: 
                                [NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption, 
                                [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil]; 

       if (![__persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:defaultStoreURL options:options error:&error]) 
       {            
           NSLog(@"Failed with error:  %@", [error localizedDescription]); 
           abort(); 
       }    

       // Check for the existence of incrementalStore 
       // Add incrementalStore 
       if (incrementalStoreExists) { 
           if (![__persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:incrementalStoreURL options:options error:&error]) 
           {            
               NSLog(@"Add of incrementalStore failed with error:  %@", [error localizedDescription]); 
               abort(); 
           }    
       } 
} 

हालांकि, वहाँ यह इस तरह से कर रही है के साथ दो समस्याएं हैं।

  1. डेटा लाने परिणाम (जैसे, NSFetchResultController के साथ) incrementalStoreURL defaultStoreURL से डेटा के अंत में जोड़ा से डेटा के साथ दिखाई देते हैं।
  2. कुछ वस्तुओं को डुप्लिकेट किया गया है। हमारे डेटा मॉडल में केवल पढ़ने के लिए कई इकाइयां हैं; जब हम को लगातार लगातार स्टोर कोऑर्डिनेटर में जोड़ते हैं तो ये डुप्लीकेट हो जाते हैं।

आदर्श रूप से, हम कोर डेटा को दो लगातार स्टोर्स से ऑब्जेक्ट ग्राफ को मर्ज करने के लिए चाहते हैं (डेटा डाउनलोड के समय दो स्टोरों के डेटा के बीच कोई साझा संबंध नहीं हैं)। साथ ही, हम डुप्लिकेट ऑब्जेक्ट्स को हटाना चाहते हैं। वेब पर खोज करते हुए, हमने लोगों द्वारा किए गए एक ही काम को करने का प्रयास करने वाले कुछ प्रश्नों को देखा - जैसे कि this answer और this answer। हमने Marcus Zarra's blog on importing large data sets in Core Data पढ़ा है। हालांकि, हमने जो समाधान देखा है, उनमें से कोई भी हमारे लिए काम नहीं करता है। हम वृद्धिशील स्टोर से डेटा को मैन्युअल रूप से डिफ़ॉल्ट स्टोर में पढ़ने और सहेजना नहीं चाहते हैं क्योंकि हमें लगता है कि यह बहुत धीमा होगा और फ़ोन पर त्रुटि प्रवण होगी। क्या मर्ज करने का एक और अधिक प्रभावी तरीका है?

हमने निम्नानुसार मैन्युअल माइग्रेशन को लागू करके समस्या को हल करने का प्रयास किया है। हालांकि, हम सफलतापूर्वक विलय होने में सक्षम नहीं हुए हैं। हम उपरोक्त संदर्भ 1 और 2 द्वारा सुझाए गए समाधान पर वास्तव में स्पष्ट नहीं हैं। मार्कस ज़रारा के ब्लॉग ने आईओएस में हमारे बड़े डेटासेट को आयात करने वाली हमारी परियोजना के शुरू में हमारे कुछ मुद्दों को संबोधित किया।

{ 
       NSError *error = nil; 
       NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys: 
                                [NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption, 
                                [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];        

       NSMigrationManager *migrator = [[NSMigrationManager alloc] initWithSourceModel:__managedObjectModel destinationModel:__managedObjectModel]; 
       if (![migrator migrateStoreFromURL:stateStoreURL 
                                type:NSSQLiteStoreType 
                             options:options 
                    withMappingModel:nil 
                    toDestinationURL:destinationStoreURL 
                     destinationType:NSSQLiteStoreType 
                  destinationOptions:nil 
                               error:&error]) 
       { 
           NSLog(@"%@", [error userInfo]); 
           abort(); 
       } 
} 

ऐसा लगता है कि इस सवाल का जवाब 1 के लेखक वृद्धिशील की दुकान से अपने डाटा पढ़ने और डिफ़ॉल्ट की दुकान में बचत समाप्त हो गया। शायद, हमने दोनों लेखों द्वारा सुझाए गए समाधान को गलत समझा है 1 & 2. हमारे डेटा का आकार हमें हमारे वृद्धिशील डेटा को डिफ़ॉल्ट स्टोर में मैन्युअल रूप से पढ़ने और पुनः डालने से रोक सकता है। मेरा सवाल यह है कि ऑब्जेक्ट ग्राफ़ को दो लगातार स्टॉरेस (जिसमें एक ही ऑब्जेक्ट मॉडल है) से एक लगातार स्टार्ट में विलय करने का सबसे प्रभावी तरीका क्या है?

स्वचालित माइग्रेशन बहुत अच्छी तरह से काम करता है जब हम ग्राफ को ऑब्जेक्ट करने या रिश्तों को संशोधित करने के लिए नई इकाई विशेषताओं को जोड़ते हैं। क्या समान डेटा को उसी लगातार स्टोर में विलय करने का एक आसान समाधान है जो रोकने और फिर से शुरू करने के लिए पर्याप्त लचीला होगा - क्योंकि स्वचालित माइग्रेशन किया जाता है?

+0

जब मुझे उसकी आवश्यकता होती है तो मार्कस ज़रारा कहां है? मैंने [NSPersistentStore migratePersistentStore: toURL: विकल्प: with टाइप: त्रुटि] विधि का उपयोग करके कुछ प्रगति की है। जहां मुझे होना चाहिए, मुझे बस कुछ और साफ कोड की आवश्यकता है। – Sunny

+0

मैं एक ही चीज़ के साथ कुश्ती कर रहा हूं। क्या आप अब तक जो पोस्ट कर चुके हैं उसे पोस्ट कर सकते हैं? मैं हार गया हूं। – damon

+0

हो गया! मुझे बताना कियह तुम्हारे लिए कैसा साबित हुआ। – Sunny

उत्तर

6

, मैं समझ गए होंगे इस काम करने के लिए कैसे। रहस्य केवल पढ़ने-योग्य इकाइयों के लिए किसी भी डेटा के बिना वृद्धिशील स्टोर डेटा बनाना है। वृद्धिशील स्टोर्स से केवल पढ़ने के लिए डेटा छोड़ने के बिना, डेटा माइग्रेशन और विलय के बाद इन इकाइयों के उदाहरण डुप्लीकेट हो जाएंगे। इसलिए, वृद्धिशील दुकानों को इन पढ़ने-योग्य इकाइयों के बिना बनाया जाना चाहिए। डिफ़ॉल्ट स्टोर एकमात्र स्टोर होगा जिसमें उन्हें है।

उदाहरण के लिए, मेरे पास मेरे डेटा मॉडल में "देश" और "राज्य" इकाइयां थीं। मुझे अपने ऑब्जेक्ट ग्राफ़ में देश और राज्य का केवल एक उदाहरण होना चाहिए था। मैंने इन इकाइयों को वृद्धिशील स्टोर्स से बाहर रखा और उन्हें केवल डिफ़ॉल्ट स्टोर में बनाया। मैंने इन इकाइयों को अपने मुख्य ऑब्जेक्ट ग्राफ़ को कम से कम लिंक करने के लिए प्रयुक्त गुणों का उपयोग किया। मैंने अपने मॉडल में सभी इकाई उदाहरणों के साथ डिफ़ॉल्ट स्टोर बनाया है। डेटा निर्माण पूरा होने के बाद बढ़ती दुकानों में या तो पढ़ने-योग्य संस्थाएं (यानी, मेरे मामले में देश और राज्य) नहीं थीं या उन्हें हटा दिया गया था।

अगला चरण वृद्धि स्टार्टअप के दौरान वृद्धिशील स्टोर को अपने स्वयं के लगातार स्टोरकॉर्डिनेटर (डिफ़ॉल्ट स्टोर के समन्वयक के समान नहीं है जिसे हम सभी सामग्री माइग्रेट करना चाहते हैं) में जोड़ना है।

अंतिम चरण अपने डेटा को मुख्य (यानी, डिफ़ॉल्ट) स्टोर में मर्ज करने के लिए incremental store पर migratePersistentStore विधि को कॉल करना है। Presto!

निम्नलिखित कोड खंड ऊपर वर्णित पिछले दो चरणों को दर्शाता है। मैंने काम करने के लिए मुख्य डेटा स्टोर में वृद्धिशील डेटा को मर्ज करने के लिए अपना सेटअप करने के लिए इन चरणों को किया।

{ 
    NSError *error = nil; 
    NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys: 
    [NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption, 
    [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil]; 

    if (![__persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:defaultStoreURL options:options error:&error]) 
    {    
     NSLog(@"Failed with error: %@", [error localizedDescription]); 
     abort(); 
    }  

    // Check for the existence of incrementalStore 
    // Add incrementalStore 
    if (incrementalStoreExists) { 

     NSPersistentStore *incrementalStore = [_incrementalPersistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:incrementalStoreURL options:options error:&error]; 
     if (!incrementalStore) 
     { 
      NSLog(@"Unresolved error %@, %@", error, [error userInfo]); 
      abort(); 
     }  

     if (![_incrementalPersistentStoreCoordinator migratePersistentStore:incrementalStore 
      toURL:_defaultStoreURL 
      options:options 
      withType:NSSQLiteStoreType 
      error:&error]) 
     { 
      NSLog(@"%@", [error userInfo]); 
      abort(); 

     } 

     // Destroy the store and store coordinator for the incremental store 
     [_incrementalPersistentStoreCoordinator removePersistentStore:incrementalStore error:&error]; 
     incrementalPersistentStoreCoordinator = nil; 
     // Should probably delete the URL from file system as well 
     // 
    } 
} 
+0

क्या आप इस समाधान के प्रदर्शन पर टिप्पणी कर सकते हैं जो इस विकल्प पर विचार कर रहा है, मैन्युअल रूप से एक स्टोर से डेटा को मैन्युअल रूप से पढ़ और लिख रहा है? –

1

आपका माइग्रेशन काम नहीं कर रहा है क्योंकि प्रबंधित ऑब्जेक्ट मॉडल समान है।

तकनीकी रूप से, आप "डेटा माइग्रेशन" के बारे में बात नहीं कर रहे हैं "स्कीमा माइग्रेशन" नहीं। CoreData का माइग्रेशन एपीआई स्कीमा माइग्रेशन के लिए डिज़ाइन किया गया है, जो प्रबंधित ऑब्जेक्ट मॉडल में परिवर्तनों को संभाला जा रहा है।

जहां तक ​​एक स्टोर से दूसरे स्टोर में डेटा स्थानांतरित किया जाता है, आप अपने आप पर निर्भर हैं। कोरडाटा आपके fetch अनुरोधों पर बैचिंग और लाने की सीमा का उपयोग करके कुशल होने में आपकी सहायता कर सकता है, लेकिन आपको तर्क को स्वयं लागू करने की आवश्यकता है।

ऐसा लगता है कि आपके पास दो लगातार स्टोर हैं, एक बड़ा और एक छोटा सा। छोटे स्टोर को लोड करने के लिए प्राथमिक कुंजी या विशिष्ट पहचानकर्ताओं के सेट की खोज करना, छोटे को लोड करना और इसका विश्लेषण करना सबसे प्रभावी होगा।

आप फिर उन पहचानकर्ताओं के लिए बड़ी दुकान से पूछकर आसानी से डी-डुप्ली कर सकते हैं।

NSFetchRequest के लिए दस्तावेज़ आपके प्रश्नों तय करने के लिए एपीआई है:

https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/CoreDataFramework/Classes/NSFetchRequest_Class/NSFetchRequest.html

+0

मेरे प्रश्न का उत्तर देने के लिए धन्यवाद। तकनीकी रूप से, कोर डेटा माइग्रेशन स्कीमा माइग्रेशन से अधिक करना प्रतीत होता है। मेरा सवाल यह पता लगाने की कोशिश कर रहा है कि लाइन कहां है और मैं नौकरी करने के लिए पहले से ही क्या फायदा उठा सकता हूं। मैं ब्रूट फोर्स से बचना चाहता हूं - क्योंकि इसके परिणामस्वरूप कोड को बनाए रखना मुश्किल होगा क्योंकि ऐप्पल अधिक से अधिक विशेषताओं को पेश करता है। मैंने [NSPersistentStore migratePersistentStore ::::] विधि का उपयोग करके कुछ प्रगति की है। मैं लगभग वहाँ हूँ। मैं किसी ऐसे व्यक्ति को अनुभव करना चाहता हूं जो मैं करने की कोशिश कर रहा हूं, मुझे सलाह दे सकता है। – Sunny

1

आप किसी भी प्रवास जरूरत नहीं है - प्रवास NSManagedObjectModel में परिवर्तन लाने के लिए, डेटा अपने आप में नहीं बनाया गया है।

आपको वास्तव में जो चाहिए वह एक पर्सिस्टेंट स्टोर समन्वयक है जो दो निरंतर स्टोर का प्रबंधन करता है। यह थोड़ी मुश्किल है, लेकिन वास्तव में बहुत मुश्किल नहीं है।

एक समान प्रश्न है, जो आपको समझा सकता है, आपको वास्तव में क्या करना है। Can multiple (two) persistent stores be used with one object model, while maintaining relations from one to the other?

यहाँ कई प्रयासों के बाद मार्कस Zarra द्वारा एक अच्छा arcticle है

http://www.cimgf.com/2009/05/03/core-data-and-plug-ins/

+0

हाय @ निकिता, मेरे प्रश्न का जवाब देने के लिए धन्यवाद। मेरा मानना ​​है कि माइग्रेशन प्रबंधक स्कीमा माइग्रेट करने से अधिक करता है। इसलिए, जब आप अपनी स्कीमा में कोई विशेषता जोड़ते हैं और स्वचालित माइग्रेशन चालू करते हैं तो आपका डेटा माइग्रेट हो जाता है। एक एकल persStentCoordinator का उपयोग करने के बारे में अपनी टिप्पणी के बारे में, मैं यही कर रहा हूँ। "If (incrementalStoreExists) {।" से शुरू होने वाले कोड खंड को देखें। आपके द्वारा प्रदान किए गए लिंक मेरे मुद्दे को संबोधित नहीं करते थे। मैं पहले से ही कई लगातार स्टोर का उपयोग कर रहा हूं और उन्हें प्रबंधित करने के लिए एकल समन्वयक का उपयोग कर रहा हूं। – Sunny

संबंधित मुद्दे