Search code examples
iosobjective-ccore-datansfetchrequest

What predicate do I use to fetch distinct objects in a many to one to one relationship?


The entity relations are as follows

Effect <->> EffectFilterProperty <<-> FilterProperty <<-> Filter

I need all distinct filters related to a particular effect (which can be filtered by its "name" property). What sort of predicate do I need to use for this relationship?

Relationship names are as follows:

Effect ->> EffectFilterProperty is filterPropertyValues
EffectFilterProperty -> FilterProperty is relatedFilterProperty
FilterProperty -> Filter is belongsToFilter

Solution

  • You need the inverse relationships to fetch the filters related to a effect. The precise answer depends on which inverse relationships are to-one and which are to-many. For example, if you have

    • "filterProperty" as to-one relationship from "Filter" to "FilterProperty",
    • "effectFilters" as to-many relationship from "FilterProperty" to "EffectFilterProperty",
    • "effect" as to-one relationship from "EffectFilterProperty" to "Effect",

    then you would execute a fetch request on the "Filter" entity with the predicate

    [NSPredicate predicateWithFormat:@"ANY filterProperty.effectFilters.effect.name = %@",
           theEffectName];
    

    If all inverse relationships are to-one then omit the "ANY". If more than one inverse relationship is to-many then it is slightly more complicated and you need a predicate using "SUBQUERY".

    Update according to the updated question: "ANY" does not work with more than one nested to-many relationship, you need a "SUBQUERY":

     [NSPredicate predicateWithFormat:@"SUBQUERY(filterProperties, $fp, ANY $fp.effectFilterProperties.effect.name = %@).@count > 0", effectName];
    

    About fetching "distinct" objects: A fetch request always returns distinct managed objects, it will never return the same object twice. - If you need objects having distinct values for some or all attributes, then you have to set the fetch request resultType to NSDictionaryResultType and returnsDistinctResults to YES.