Core data many-to-many relationship - Predicate question
Asked Answered
S

4

29

In my Core Data model I have two entities: List and Patient. List has an attribute called 'name'.

A List can have any number of Patients and each Patient can belong to any number of different lists. I have therefore set a relationship on List called 'patients' that has an inverse to-many relationship to Patient AND a relationship on Patient called 'lists' that has a to-many relationship to List.

What I'm struggling to figure out is how to create a Predicate that will select all Patients that belong to a particular List name.

How would I go about this? I have never used relationships before in Core Data.

Skylar answered 24/2, 2010 at 18:45 Comment(0)
S
23

This seems to work OK:

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(ANY lists == %@)", myList];

Where myList is an actual List entity.

Skylar answered 30/3, 2010 at 6:23 Comment(0)
H
20

Given a data model like:

List <<——>> Patient,

you can find all Patient instances that belong to a list with a particular name with a fetch request on the Patient entity using a predicate like:

[NSPredicate predicateWithFormat:@"ANY lists.name LIKE[cd] %@", listName]

assuming listName is an NSString instance with the list name you want. LIKE[cd] does a case-insensitive and diacritic-insensitive comparison.

Hartzel answered 24/2, 2010 at 18:54 Comment(1)
I have the List entity in memory and I pass it to a UITableViewController subclass. How would I construct a fetch request to grab all patients from that list entity? I'm trying to use a NSFetchedResultsController and a list's name is not unique (so constructing a predicate based on name alone could cause errors).Skylar
W
12

It sounds like your data model is this:

List <<-->> Patient

I would think that if you know the particular list name, then you know the particular list object. If so, you can just grab the patients using the to-many relationship from List to Patient--it is a set of patient objects. For example, if the relationship from List to Patient is named "patients":

NSSet *patientSet = listObject.patients;

Note: this requires that you create subclasses for your managed objects so you can access the attributes and relationships as properties on your objects.

If you only know the list name for some reason, and you are fetching Patient objects, then you can create a predicate using the to-many relationship from Patient to List (assume it's named "lists" and the list's name in a string named "listName"):

NSPredicate *pred = [NSPredicate predicateWithFormat:@"ANY lists.name == %@",listName];
Wilmott answered 24/2, 2010 at 18:50 Comment(3)
In the first example (which is correct as usual from gerry3), you can access it via KVC without having to subclass it using NSSet *patientSet = [listObject valueForKey:@"patients"];Cincinnatus
But how do you "convert" that into Fetched results controller? I also have the same question and I do have the reference to the "list" object, but I would like to have a fetched results controller that shows "list.patients"Cynosure
Actually nevermind, the answer from @Garry below is what I was looking forCynosure
I
7

Ten years later, some more info !

Just some more info on the fantastic @GarryPettet answer,

Say you have entity CD_Person and aPerson is one of those. IE:

var aPerson: CDPerson

Say you have an entity CD_Pet

CD_Person has a relationship .pets which is a one-to-many CD_Pet

So just to be clear,

aPerson.pets

is indeed a Set of CD_Pet entities.

Almost certainly you'll have an id field which comes from your data source.

(Aside, .id must be an Int64 in your core data entity, even if it's a smaller int in your source data)

Two ways to go!

BOTH this

let p = NSPredicate(format: "(ANY pets == %@)", aPerson )

AND this

let p = NSPredicate(format: "(ANY pets.id == %lld)", aPerson.id)

... work perfectly, both are possibilities.

So there's two ways to go!

(PS: Don't forget the lld .. @ won't work for Int64!)

Both work fine in the common situation where you have a "many-to-many" relationship.

Interpreter answered 11/3, 2020 at 13:33 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.