Note that there are some explanatory texts on larger screens.

plurals
  1. POFinding objects in Core Data by array attribute, performantly in >10k elements
    primarykey
    data
    text
    <p>Short:<br> I need to <strong>find core data objects by</strong> a key, which holds a <strong>unique immutable array</strong> (fixed length, but chosen at runtime) of arbitrary objects (for which not only <strong>element membership</strong>, but also <strong>element order</strong> determines <strong>uniqueness</strong>). <strong>NSManagedObject</strong> however <strong>forbids overriding</strong> <code>[isEqual:]</code>. Now what?</p> <hr> <p>Long:<br> I have an entity (see diagram image for entity "…Link") in my Core Data model for which I have to guarantee uniqueness based on an attribute key ("tuple"). So far so good.</p> <p>The entity's <strong>unique attribute</strong> however has to be an <strong>NSArray</strong>.<br> And to make things a bit more difficult I <strong>neither know the class type</strong> of the <strong>tuple's elements</strong>.<br> Nor do I know the tuple's element count. Well, actually the count is the same for every tuple (per core data context at least), but not known before the app runs.</p> <p>There must <strong>only ever be one instance</strong> of my link entity <strong>with a given tuple</strong>.<br> And for obvious reason only ever one tuple instance with a given array of arbitrary objects.<br> Whereas two tuples are to be considered equal if <code>[tuple_1 isEqual:tuple_n]</code> returns <code>YES</code>. <strong>NSManagedObject forbids the overriding</strong> of <code>[isEqual:]</code> and <code>[hash]</code> though, otherwise things would be pretty much a piece of cake.</p> <p><strong>"…Tuple" objects</strong> are created together with their array of tokens (via a convenience method) and <strong>are immutable</strong> (and so is each "…Token" and its data attribute). (think of "…Tuple" as a "…Link"'s dictionary key.)</p> <p>"…Tuple" implements <code>"- (NSArray *)tokens;"</code>, which <strong>returnes a neatly ordered array of tokens</strong>, based on the "order" keys of "…TokenOrder". (<strong>Tuples</strong> are expected to <strong>contain at most 5 elements</strong>.)</p> <p>I however <strong>expect to have tens of thousands</strong> (potentially even more in some edge cases) of "…Link" objects, which I have to (frequently) <strong>find based on their "tuple" attribute</strong>.</p> <p>Sadly I couldn't find any article (let alone solution) for such a scenario in any literature or the web.</p> <p>Any ideas?</p> <p><img src="https://i.stack.imgur.com/sn2kd.jpg" alt="core data model"></p> <p>A possible solution I've come up with so far would be:</p> <ol> <li><p>Narrow amount of elements to compare by tuple by adding another attribute to "…Tuple" called "<code>tupleHash</code>", which is pre-calculated on object creation via: <strong>Snippet 1</strong></p></li> <li><p>Query with NSPredicate for objects of matching tupleHash (narrowing down the list of candidates quite a bit).</p></li> <li><p>Find "…Link" featuring given tuple in narrowed candidate list by: <strong>Snippet 1</strong></p></li> </ol> <p><strong>Snippet 1:</strong></p> <pre><code>NSUInteger tupleHash = [[self class] hash]; for (id token in self.tokens) { tupleHash ^= [token.data hash]; } </code></pre> <p><strong>Snippet 2:</strong></p> <pre><code>__block NSArray *tupleTokens = someTokens; NSArray *filteredEntries = [narrowedCandidates filteredArrayUsingPredicate: [NSPredicate predicateWithBlock: ^(id evaluatedObject, NSDictionary *bindings) { return [evaluatedObject.tuple.tokens isEqualToArray:tupleTokens]; }]]; </code></pre> <p><em>(Sorry, markdown appears to oppose mixing of lists with code snippets.)</em></p> <p>Good idea of or just insane?</p> <p>Thanks in advance!</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload