0

I have a model with a Verse entity that has a many-to-many relationship to a Word entity.

I'd like to find verses that contain all words that a user is searching for.

I'm guessing that it could be done with a predicate like

    "ANY words.word == %@ AND ANY words.word == %@ AND ...", term1, term2, ...

Can this use some type of word->Verse index, to avoid having to compare every verse's words against term1?

If not, how should the (model or) predicate be changed to make this fetch more efficient?

2 Answers2

1

I would create a NSPredicate for each term, and then use a andPredicateWithSubpredicates: NSCompoundPredicate to perform the search. If it is a live search, reload the search results on a space, or reload on every character and use one predicate with CONTAINS.

Siriss
  • 3,737
  • 4
  • 32
  • 65
1

First, you can just do a contains in one predicate:

[NSPredicate predicateWithFormat:"ANY words.word CONTAINS %@", arrayOfWords];

But, that will be slow. String compares are slow. Case and diacritic insensitive are almost the slowest. You are better off having another property on your Word entity that is for searching where you strip out the case and the diacritic and then search against that field. Your search performance will be much higher.

Marcus S. Zarra
  • 46,571
  • 9
  • 101
  • 182
  • Useful. I'll have an attribute specifically designed for that, so the search is insensitive. Can I do an exact comparison, instead of CONTAINS[n]? Would this utilize an index of words, to be more efficient? (Or search from the word->Verse direction?) –  Jul 16 '15 at 19:48
  • You can add an index which will definitely help performance. You can also do an exact search but then you would need to go word for word again. If you are searching for multiple words then the CONTAINS will perform better. Not great, but better. – Marcus S. Zarra Jul 18 '15 at 15:46