1

I am having a CoreData structure. It is working fine for me. Now I am trying to do an interesting FetchRequest, however I am struggeling to find the correct predicate.

I am having two ententies, Person and Venues. A person can be connected to many venues, but only once to the same venue. And other way around.

I have created a mapping table, which saves the person and venue as relationships. Everything is working fine here. I even implemented the inverse relationship.

enter image description here

In the picture left is my venue. I want to Fetch all persons based on a current venue, where there is NO Mapping created already.

My approach was to use pk_venue, which gives me a set of PersonVenueMapping. However, how can I only use the persons of that Set.

fetch.predicate = NSPredicate(format: "NOT (person IN %@)", venue!.pk_venue[HELP])

I came up with that Predicate. However, how can I access the persons of that set? I would need a array/ set of only the persons, that are connected to that current object.


Edit: Just to give you example.

Person: Max, Leon, Henry
Venue: Venue1, Venue2, Venue 3, Venue 4

PersonVenueMapping: Max <-> Venue1

Now when I select Max, I want Venue2 & Venue3 & Venue4

Thanks in advance

10
  • 1
    Why do you need a mapping entity, why not create a many-to-many mapping between Person and Venue? Commented Mar 11, 2020 at 14:33
  • 1
    No but maybe you don't need 3 relationships like that depending on what a role is in this context. Commented Mar 11, 2020 at 14:40
  • 1
    If the design is that a Person has a Role for a Venue then the relationships should mirror that. Commented Mar 11, 2020 at 14:57
  • 1
    This seems very much like you are treating CoreData like a database when it actually isn’t one. Model your data in a way that the app will display it. Not in a way that a normalised SQLite database might look. Commented Mar 12, 2020 at 9:02
  • 1
    @Fogmeister Thanks.. yes you are right. I am still getting used to CoreData coming from regular relational databases. You also mean I won't need a mapping table? Commented Mar 12, 2020 at 9:06

2 Answers 2

1

Your model looks very much like a normalised database type model. CoreData is not a database and so some of the requirements of modelling data are more flexible when using it. For instance many to many relationships are possible (and encouraged).

Create your model in this way...

Person
------
name: String
------
assignedVenues: Many relationship to `venue` type

Now every relationship has an inverse property, so...

Venue
------
name: String
------
managers: Many relationship to `Person` type

Now you can go from Max to his assigned venues just by doing...

let selectedPerson = // fetch Max from CoreData

let venues = selectedPerson.assignedVenues

Equally you can go from a venue to find all the people managing it...

let someVenue = // fetch venue from CoreData

let managers = someVenue.managers

To satisfy your question of finding all venues that Max is not managing you can now do a query like...

let selectedPerson = //fetch Max

let predicate = NSPredicate(format:"NONE managers == %@", selectedPerson) // Its been a long time since I did CoreData so forgive me if this syntax isnt correct but the idea is correct. :D

You can now use that predicate to get all venues where max is NOT one of the managers of the venue.

By removing the "mapping" that is required in something like SQLite etc... you can make things much simpler for yourself.

Sign up to request clarification or add additional context in comments.

4 Comments

Wow.. thanks for taking the time and writing that down :) I appreciate. Really learned something very helpful again. I will make changes to my CoreData structure and try your query aswell.
@davidev Glad I could help. :D There are some really excellent tutorials on raywenderlich.com that cover a lot of really useful tips on how to use CoreData. Definitely worth a read.
Still one question arise.. I still need to store a role for one relationship. However, I can not store that attribute in the person entity or venue as there can be more relationships with different roles. How can I use that in your approach?
In that case you could possibly replace your Mapping type with Role and use that as the mapping. I guess it comes down to your specific model requirements which would take a while to look in to. So you could just have Person <->> Role <<-> Venue or something like that. There might be other better ways of doing this also. With this I think your venue predicate could be something like NONE jobs.manager == %@ but now I'm going beyond what my memory is able to store. :D Where jobs is the many relationship from venue ->> role
1

I am confused as to whether you are fetching persons with no mapping to a given venue, or venues with no mapping to a given person. I’ll assume the latter.

Your fetch request will therefore be for the entity Venue. Let’s call the selected Person selectedPerson. The following predicate should return only those Venues that have no mapping to selectedPerson:

NSPredicate(format:”SUBQUERY(pk_venue, $M, $M.person == %@).@count == 0”, selectedPerson)

or in natural language “fetch Venues for which the count of mappings ($M), with person equal to the selected person, is zero”.

1 Comment

Appreciate the answer sir. Will test, yeah it is indeed correct what you said at the end. That is what I want to achieve

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.