3

enter image description here

public enum Ability: String {
  case newcomer = "Newcomer"
  case beginner = "Beginner"
  case intermediate = "Intermediate"
  case advanced = "Advanced"
}

public enum Group: String {
  case solo = "Solo"
  case duo = "Duo"
  case team = "Team"
}

I want to find all performances that match the following.

ability == "Beginner"
group == "Duo"
performers == "Jane Davies" && "Alice Evans"

The documentation suggests that aggregate operations in core data are not supported, which is surprising. Questions like this have been asked before here and suggest the use of 'Any'.

To my understanding, 'Any' would return performances that include 'Jane' or 'Alice' or 'Jane & Alice' right? I just want performances that include both 'Jane & Alice'.

How would I write a predicate for this query?

Thanks

  • Do you want to test against a string array or against an array of (two) Performer objects? – Martin R Oct 29 '17 at 14:12
  • Hi @MartinR I'm interested in both. –  Oct 29 '17 at 14:15
  • You already accepted an answer, so apparently the problem is solved. – I just wonder because that predicate would give all objects which include "Jane" **or** "Alice" as a performer, and does not honor the last name at all. – Martin R Oct 29 '17 at 14:16
  • Your right @MartinR –  Oct 29 '17 at 14:17
  • Would you like to submit a solution @MartinR ? –  Oct 29 '17 at 14:23

1 Answers1

1

With a list of (distinct) Performer objects, the following predicate should work to find all Performance objects which are related exactly to those performers:

let perf1 = ... // Performer object for "Jane Davies"
let perf2 = ... // Performer object for "Alice Evans"
let list = [perf1, perf2]

let predicate = NSPredicate(format: "performers.@count = %ld AND ALL performers in %@", list.count, list)

but apparently is doesn't. The workaround is to use a SUBQUERY:

let predicate = NSPredicate(format: "performers.@count = %ld AND SUBQUERY(performers, $p, $p in %@).@count = %ld",
      list.count, list, list.count)
Martin R
  • 529,903
  • 94
  • 1,240
  • 1,382
  • This works "performers.@count = %ld AND ANY performers in %@" but this doesn't "performers.@count = %ld AND ALL performers in %@" –  Oct 29 '17 at 14:30
  • @robdashnash: That is strange, because the first one would match a performance with performers = ["Jane Davies", "SomeOne Else"] – Martin R Oct 29 '17 at 14:33
  • I agree. [error] error: exception handling request: , Unsupported predicate group == "Duo" AND ability == "Newcomer" AND performers.@count == 2 AND ALL performers IN { (entity: Performer; id: 0xd000000000480004 ; data: ), (entity: Performer; id: 0xd0000000004c0004 ; data: )} with userInfo of (null) –  Oct 29 '17 at 14:35
  • It looks like 'ALL' is not supported by core data https://stackoverflow.com/a/17097033/1951992 but here you can see dave de long suggests otherwise https://stackoverflow.com/a/4217889/1951992 –  Oct 29 '17 at 14:37
  • Does this work? `NSPredicate(format: "performers.@count = %ld AND SUBQUERY(performers, $p, $p in %@).@count = %ld", list.count, list, list.count)` – Martin R Oct 29 '17 at 14:38
  • 1
    Looks like a bug, similar to this one https://stackoverflow.com/a/19716571/1187415 or this one https://stackoverflow.com/a/14473445/1187415 – and SUBQUERY is a workaround. – Martin R Oct 29 '17 at 14:42