0

Below is a graph of relationships. I have a set of Recipes that I have retrieved and a set of BaseIngredients. I want to return a set of recipes that contain all of those ingredients. My current predicate

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF IN %@ AND ingredientSections.ingredients.baseIngredient IN %@", recipes, self.ingredientsFilter];

fails miserably. What is the correct way of doing this?

Object Graph

Cameron Lowell Palmer
  • 21,528
  • 7
  • 125
  • 126

1 Answers1

1

With a nested to-many relationship, you probably need a SUBQUERY.

The following predicate returns all recipes where any base ingredient of any ingredient section is in the given set:

[NSPredicate predicateWithFormat:@"SELF IN %@ AND SUBQUERY(ingredientSections, $s, ANY $s.ingredients.baseIngredient IN %@).@count > 0",
     recipes, self.ingredientsFilter];

But unfortunately, that is not exactly what you need. To get all recipes that have a section containing all of the given ingredients, the following might work:

[NSPredicate predicateWithFormat:@"SELF IN %@ AND SUBQUERY(ingredientSections, $s, SUBQUERY($s.ingredients, $i, $i.baseIngredient IN %@).@count == %d).@count > 0",
     recipes, self.ingredientsFilter, [self.ingredientsFilter count]];
Martin R
  • 529,903
  • 94
  • 1,240
  • 1,382
  • Also if the list of ingredients is greater than one will it require all of the base ingredients be present? – Cameron Lowell Palmer Jul 24 '13 at 09:58
  • @CameronLowellPalmer: Unfortunately, SUBQUERY is badly documented. Perhaps start with http://stackoverflow.com/questions/3810992/quick-explanation-of-subquery-in-nspredicate-expression. If that does not help, I will try to explain more. – Martin R Jul 24 '13 at 10:01
  • @CameronLowellPalmer: The above predicate returns all recipes where any base ingredient of any ingredient section is in the given set. If that is not what you want, please update the question. – Martin R Jul 24 '13 at 10:03
  • Updated to reflect the request that the resulting set of recipes should contain all of the ingredients. BTW I'm really grateful for the rapid answer. – Cameron Lowell Palmer Jul 24 '13 at 10:27
  • @CameronLowellPalmer: Would it be sufficent to find all recipes that have an ingredient section containing all the given ingredient? Or is it necessary to consider the case that one section contains one part of the given ingredients and another section contains the remaining parts? - I think that I would have an answer for the first (simple) case, but I am not sure how to handle the second case in a single fetch request. – Martin R Jul 24 '13 at 11:00
  • Great question. I'm thinking that I may need to do the latter, but I would still be interested in the simple case. – Cameron Lowell Palmer Jul 24 '13 at 11:06
  • @CameronLowellPalmer: I have updated the answer. I think that *should* work, but did not yet test it. – Martin R Jul 24 '13 at 11:27
  • I believe that last %@ should be %d. I also used this to find all ingredients within the recipes you're looking at BaseIngredients predicate = [NSPredicate predicateWithFormat:@"SUBQUERY(ingredients, $i, ANY $i.ingredientSection.recipe IN %@).@count > 0", recipes]; – Cameron Lowell Palmer Jul 24 '13 at 11:34
  • @CameronLowellPalmer: Fixed %@ -> %d. – Martin R Jul 24 '13 at 11:41