1

I'm a bit lost, and I hope you can help me.

I have two arrays

let stars = ["Paul", "Ringo"]
let visitors = ["bob", "mary"]

Then I have Core Data entities Rockstar and Person. And a one-to-many relation fans between the two.

Now I want to find a couple of specific Rockstars, and make sure that they don't have visitors as fans.

I try to do that with a compound predicate, roughly like this:

let starsPredicate = NSPredicate(format: "id IN %@", stars)
let fansPredicate = NSPredicate(format: "NOT (fans.personid CONTAINS %@)", visitors)

and finally

let compoundPredicate = NSCompoundPredicate(andPredicateWithSubpredicates: [starsPredicate, fansPredicate])

I'm afraid this results in two questions:

  1. What is the correct syntax for the fansPredicate? It works fine with one value, but it crashes on an array

  2. Is this possible with a compound predicate at all? I think if the Person entity is empty, I get zero records from the compoundPredicate.

Sjakelien
  • 2,255
  • 3
  • 25
  • 43
  • Shouldn't you use the same logic "IN" for fans? See https://stackoverflow.com/questions/8580715/nsarray-with-nspredicate-using-not-in then ? – Larme Jul 21 '21 at 09:35
  • tried that, crashes – Sjakelien Jul 21 '21 at 09:38
  • If it crashes, you might want to share the error message in console? – Larme Jul 21 '21 at 09:39
  • [error] error: SQLCore dispatchRequest: exception handling request: , unimplemented SQL generation for predicate : (fans.personid IN {"173A0057-C55D-4F1E-9CD8-42627813F822"}) with userInfo of (null) – Sjakelien Jul 21 '21 at 09:40
  • You probably need a SUBQUERY, something like `NSPredicate(format: "SUBQUERY(fans, $f, $f.personid IN %@).@count = 0", visitors)` – Martin R Jul 21 '21 at 09:45
  • @MartinR Thanks. That is what I was thinking. I'm just not very good at SQL stuff. But this makes sense. I will give it a try – Sjakelien Jul 21 '21 at 09:53
  • @MartinR: I think you nailed it. Feel free to post it as an answer. I will reward you. You basically answered both my questions. – Sjakelien Jul 21 '21 at 10:05

1 Answers1

1

This can be achieved with a “SUBQUERY”:

let fansPredicate = NSPredicate(format: "SUBQUERY(fans, $f, $f.personid IN %@).@count = 0",
                                visitors)

The predicate is true for all Rockstar objects which have no related Person object whose personId is in the given list.

Martin R
  • 529,903
  • 94
  • 1,240
  • 1,382