NSPredicate Compare Two Sets And Many-To-Many Relationship - ios

Two model classes
AUser
- name
AGroup
- users
Groups and Users share a many-to-many relationship.
I wish to check whether two sets share the exact same users (not more users or less users)
But unfortunately I am getting the following error: to-many key not allowed here
Note that I have looked at other SO questions but none seemed to fit because I have tried to use their methodologies for the past 2 hours, but I could not get it to work. Or at least I did not understand them very well.
Also is my predicate alright for comparing two mutable sets?
- (BOOL)conversationExists:(NSMutableSet *)members {
NSFetchRequest *request= [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"AGroup" inManagedObjectContext:_managedObjectContext];
NSPredicate *predicate =[NSPredicate predicateWithFormat:#"users==%#",members];
//There is more code that I have not shown here as it is irrelevant to the question
//Mainly The NSPredicate line is the problem
}
Thank you so much for your time. I really appreciate it.
From,
New iOS programmer

Why does it need to be a predicate?
What's wrong with [[groups valueForKey:#"users"] isEqualToSet:members]?

This post had an answer: How to use the "ALL" aggregate operation in a NSPredicate to filter a CoreData-based collection
Essentially something like this:
[NSPredicate predicateWithFormat:#"SUBQUERY(members, $member, $member IN %#).#count = %d", members, [members count]];

Related

CoreData Predicate That Compares Two Properties in a Too-Many Relationship

I'm trying to build a predicate that compares two members of a too-many relationship.
The code below more clearly shows my intention, but doesn't seem to work (assume objects is the too-many relationship and has members, member1 and member2):
[NSPredicate predicateWithFormat:
#"(ANY objects.member1 ==[cd] objects.member2)"];
I appreciate any help in determining a properly structured predicate for this type of comparison.
Assuming that you want to fetch the objects which are related to at least one object with
"member1 == member2", you have to use a SUBQUERY:
[NSPredicate predicateWithFormat:#"SUBQUERY(objects, $o, $o.member1 == $o.member2).#count > 0"]
You can find a similar example in the NSExpression Class Reference.

"multiple to-many keys not allowed here" issue with a predicate

I need some help with a predicate for a NSFetchedResultsController. My guess is that can be done with a SUBQUERY but I can not figure out how.
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:#"Album"];
fetchRequest.predicate = [NSPredicate predicateWithFormat:#"ANY tracks.playlistItems.playlist == %#", section.playlist];
When executing a fetch request with this predicate I get a “multiple to-many keys not allowed here” error. Which makes sense since album has multiple tracks, and a track has multiple playlist items.
So using natural language here is what I want from this predicate: an album where at least one of its tracks has at least one of its playlistItems that has the following playlist.
Can I achieve this using a SUBQUERY in my predicate?
(I know that this can be easily achieved using 2 fetch requests, but I was wondering if this can be done using one request, since I am using a NSFetchedResultsController)
Yes, you can do this using a SUBQUERY. I have only ever used subqueries a couple of times, but I think yours should look like this:
fetchRequest.predicate = [NSPredicate predicateWithFormat:#"SUBQUERY(tracks, $t, ANY $t.playlistItems.playlist == %#).#count != 0", section.playlist];

Using NSFetchRequest with complex NSPredicate in a NSFetchRequestController

Im trying to implement something that I'm sure have been implemented a million times before, a search in the core data database, displayed in a table using a fetchRequestController and the searchController.
My problem is writing the NSPredicate for the NSFetchRequest. According to the NSPredicate guide by Apple, not everything you can do in Sqlite is possible with core data.
I have been trying to find a solution for some time, but maybe one of you can use his experience to help me.
CoreData DB description:
Shops has a MANY TO MANY relationship with DiscountProgam.
My use case is as follows: I need to filter out Shops who's name/address/zip/city contains the search string. that's the easy part.
The hard part is creating the section of the database I want to filter from, because I have an array of "active" discountPrograms UID's, and I only want shops that have one of the active discount programs in their "discountPrograms" set. So in pseudo code that would be:
FROM Shops who have at least one discountProgram who's uid IN activeDiscountProgramsArray WHERE name/address/zip/city CONTAINS searchString
Is this possible? am I over reaching the limits of predicates?
If so, how could I do it differently?
Yes, NSPredicate can analyse both the direct attributes of the target entity of a fetch and the attributes of its relationships. Try:
NSArray *validUIDs = ...;
NSString *searchTerm = ...;
[NSPredicate predicateWithFormat:#"(name CONTAINS[cd] %# OR zip CONTAINS[cd] %#) AND (SUBQUERY(discountProgram, $d, $d.UID IN %#).#count > 0)", searchTerm, searchTerm, validUIDs];

CoreData NSPredicate with two one-to-many relations

I have a CoreData model data structure like this for restricting information based on the group a user belongs to:
Category <->> Information <->> Groups.
I have an NSSet of UserGroups objects. I want to be able to filter categories based on the NSSet of Group objects, such that if a category does not contain any pieces of information which have any groups inside my NSSet, they will not be returned by my predicate.
For information I can do
[NSPredicate predicateWithFormat:#"ANY groups in (%#)",groups];
For categories I've tried the following with only a crash:
[NSPredicate predicateWithFormat:#"ANY information.groups in (%#)",groups];
But I need to write a predicate at the Category level. I am programming under the assumption that the information in my data set is sufficiently large that I cannot pull them all of them out and process them to find my Categories. I want to create predicate that will fetch only the categories that are relevant to the user based on his/her groups.
Thanks for your help!
The following predicate on Category should work (assuming that information is the to-many relationship from Category to Information):
[NSPredicate predicateWithFormat:#"SUBQUERY(information, $i, ANY $i.groups in %#).#count > 0",groups];
Alternatively, you could use the inverse relationships:
// your set of Group objects:
NSSet *groups = ...;
// all Information objects that are related to any group object:
NSSet *information = [groups valueForKey:#"information"] ;
// all Category objects that are related to any information object:
NSSet *categories = [information valueForKey:#"category"];
which can be combined to
NSSet *categories = [groups valueForKeyPath:#"information.category"];
A disadvantage of this alternative solution might be that it creates also the intermediate set of groups in memory.

NSPredicate with Core Data not returning data

When either of the following NSPredicates are used by themselves they return the data as expected. However, when I do a compound search nothing is returned. What is incorrect with my search? I'm searching Core Data with an NSFetchRequest
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:#"File"];
NSPredicate *rootPredicate = [NSPredicate predicateWithFormat:#"fileWithContents.entityFolderRoot.object_id == %#", self.product.iqid];
NSPredicate *pathPredicate = [NSPredicate predicateWithFormat:#"fileWithContents.path == %#", self.currentFolder.path];
NSPredicate *predicate = [NSCompoundPredicate andPredicateWithSubpredicates:[NSArray arrayWithObjects:pathPredicate, rootPredicate, nil]];
request.predicate = rootPredicate;
[self performFetchWithRequest:request];
Looking at the attribute names in your predicate it seems that your data structure is perhaps unnecessarily complex. Why would an entity representing a file (File) have a to-one relationship to another file (fileWithContents) which besides a path attribute would have another to-one relationship with another entity describing some kind of folder (entityFolderRoot) which as a unique ID.
Indeed, the path attribute and the folder root relationship seem to be describing a similar thing (some kind of container), maybe the same thing. This is bound to lead to unexpected results.
Consider redesigning your data model.

Resources