2011-12-11 12 views
5

私は自分のアプリで検索を実装しようとしています。コアデータエンティティには、「タグ」と「DvarTorah」の2つがあります。タグは単なる文字列です。 「DvarTorah」にはタイトル、テキストコンテンツ、その他のプロパティがあります。私はそれらをすばやく検索する最良の方法を見つけようとしています。約1200のDvarTorahエンティティ、さらに多くのタグが付属しています。現在、検索ビューコントローラがviewDidLoadを呼び出すと、NSFetchedResultsControllerがロードされます。ユーザーが検索ボックスに入力するかスコープを変更すると、スコープバーの値と検索タームの両方を取得し、オブジェクトの配列をフィルタリングするメソッドを呼び出します。その外観は次のとおりです。このコアデータベースの検索を最適化するにはどうすればよいですか?

- (void) filterArrayWithSearchTerm:(NSString *)searchString andScopeIndex:(NSInteger)scopeIndex{ 

    if ([searchString isEqualToString:@""]) { 
     return; 
    }  

    NSMutableArray *unfilteredResults = [[[[self.fetchedResultsController sections] objectAtIndex:0] objects] mutableCopy]; 

    if (self.filteredArray == nil){ 
     self.filteredArray = [[[NSMutableArray alloc ] init] autorelease]; 
    } 

    [filteredArray removeAllObjects]; 

    NSPredicate *predicate = [[[NSPredicate alloc] init] autorelease]; 

    if (scopeIndex == 0) { 
     predicate = [NSPredicate predicateWithFormat:@"dvarTorahTitle CONTAINS[cd] %@", searchString]; 
    }else if (scopeIndex == 1) { 
     predicate = [NSPredicate predicateWithFormat:@"searchableContent CONTAINS[cd] %@", [searchString canonicalString]];    
    }else if (scopeIndex == 2){ 
     predicate = [NSPredicate predicateWithFormat:@"ANY tags.tagText CONTAINS[cd] %@", searchString]; 
    }else{ 
     predicate = [NSPredicate predicateWithFormat:@"(ANY tags.tagText CONTAINS[cd] %@) OR (dvarTorahTitle CONTAINS[cd] %@) OR (searchableContent CONTAINS[cd] %@)", searchString,searchString,searchString]; 
    } 

    for (DvarTorah *dvarTorah in unfilteredResults) { 
     if ([predicate evaluateWithObject:dvarTorah]) { 
      [self.filteredArray addObject:dvarTorah]; 
     } 
    } 

    [unfilteredResults release]; 
} 

問題は私の検索方法がひどく遅いことです。私はCONTAINSが起こりそうな原因だと知っていますが、コンテンツの標準バージョン(searchableContent)を保存してさらに最適化しようとしても、検索は恐ろしく遅いです。これをもっと速くするにはどうすればいいですか?

編集:

​​

EDIT2:ヤコブの最初の提案に基づいて

は、ここに私の新しい方法です

まだ遅い、もはや配列をコピーしない:

- (void) filterArrayWithSearchTerm:(NSString *)searchString andScopeIndex:(NSInteger)scopeIndex{ 

    if ([searchString isEqualToString:@""]) { 
     return; 
    } 

    if (self.filteredArray == nil) { 
     self.filteredArray = [[[NSMutableArray alloc ] init] autorelease]; 
    } 

    [filteredArray removeAllObjects]; 

    NSPredicate *predicate = nil; 

    if (scopeIndex == 0) { 
     predicate = [NSPredicate predicateWithFormat:@"dvarTorahTitle CONTAINS[cd] %@", searchString]; 
    }else if (scopeIndex == 1) { 
     predicate = [NSPredicate predicateWithFormat:@"searchableContent CONTAINS[cd] %@", [searchString canonicalString]];    
    }else if (scopeIndex == 2){ 
     predicate = [NSPredicate predicateWithFormat:@"ANY tags.tagText CONTAINS[cd] %@", searchString]; 
    }else{ 
     predicate = [NSPredicate predicateWithFormat:@"(ANY tags.tagText CONTAINS[cd] %@) OR (dvarTorahTitle CONTAINS[cd] %@) OR (searchableContent CONTAINS[cd] %@)", searchString,searchString,searchString]; 
    } 

    [self.filteredArray addObjectsFromArray:[[[[self.fetchedResultsController sections] objectAtIndex:0] objects] filteredArrayUsingPredicate:predicate]]; 
} 
+0

すべて平等に遅い4つのバージョンはありますか?あなたがフィルタリングしている結果セットの大きさはどれくらいですか?あなたは含まれているもの以外のものを使うことで逃げることができますか? –

+0

@DavidRönnqvist - 結果セットは約1200のオブジェクトです。おそらく私はUISearchResultsControllerを誤解しています...比較の遅さに関しては、私は目でプロファイリングしていますが、ツールを使用していないので、わかりません。私と同じように思える。 – Moshe

答えて

6

ここにはCPUサイクルとメモリを詰め込んでいるものがたくさんあります。

1つは、NSFetchedResultsControllerからフェッチされた結果のコピーを変更しています。どうして?

2つは、上記の結果にfor..in構造を使用し、それぞれに-[NSPredicate evaluateWithObject:]を呼び出しています。代わりに、-[NSArray filteredArrayUsingPredicate:]で動作するように述語検索文字列を修正することができます。これは、あなたのアプローチよりもおそらく早いです。

3つで、predicateという変数には微妙な問題があります。最初に自動解放されたもの以外の何かに常に割り当てます。デフォルト値はnilです。

4つの述語文字列は、前述したように、むしろ非効率的です。 というインデックス番号などを実行する必要があると思います。

http://developer.apple.com/library/mac/#documentation/cocoa/conceptual/CoreData/Articles/cdPerformance.html

http://cocoawithlove.com/2008/03/testing-core-data-with-very-big.html

http://cocoawithlove.com/2009/11/performance-tests-replacing-core-data.html

http://www.mlsite.net/blog/?page_id=1194

Is SQLite FTS3 still the best way to go for rolling out your full text search?

:コアデータを全文検索で

詳しい情報

sqlite Indexing Performance Advice

Full Text Searching in Apple's Core Data Framework

+1

NSFetchedResultsControllerで 'filteredArrayUsingPredicate'を呼び出せますか?そうでない場合は、クラスメソッドとして使用できますか?そうでない場合は、追加の配列が必要です。私の更新されたコードを見てください。そして、はい、コンテナはここで私の最大の問題です。 – Moshe

関連する問題