I have an NSMangedObject that contains NSSet of other NSManagedObjects.
I need to check if these objects has an value in NSSet and then return them.
I use MagicalRecord for fetching data.
So I need something like this:
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"stringObjects contains %#", string];
So if NSSet stringObjects contains some string that I am looking for so then return object I have requested.
One note here: stringObjects (name just for example it represent my NSSet) it is NSSet that contains NSManagedObjects, so I need to search them by some id (for example string_id attribute).
So then model looks like this
NSSet *set = MainObject.stringObjects;
NSString *string_id_for_first_object = [[[set allObjects] objectAtIndex:0] string_id];
Just for better understanding relationship.
But the question is about how can I create predicate to check if NSSet contains needed id.
If I understand your question correctly, stringObjects is a to-many relationship
from one entity A to another entity B, and B has an attribute string_id.
To find all A objects that are related to any B object with the given string id, use:
NSString *stringId = …; // The string that you are looking for
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"ANY stringObjects.string_id == %#", stringId];
Related
I have an NSArray of this NSManagedObject class lets call it People, inside there is a relationship to-one for another NSManagedObject class let call it Car, I want to predicate an NSArray of the first class which will get me an ID of a car. I'm doing it like this:
DbCar *c = [self.cars firstObject];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"car.idNum == %#", c.idNum.stringValue];
NSArray *sorted = [self.mainData filteredArrayUsingPredicate:predicate];
self.sortedData = sorted;
self.mainData is an NSArray that hold 'People' NSManagedObject
For some reason I always get nil.
Thanks in advance.
For NSNumber type of properties don't need to pass stringValue property of that number. Directly pass that number object itself as an argument to the predicate as follows:
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"car.idNum == %#", c.idNum];
This will help!
I am using core data to fetch a list of objects. These objects have a property named 'categories'. This categories property is a NSDictionary constructed from json like :
#{#"A":#YES, #"B":#NO, #"C":#YES}
I want to get all core data objects which category is true for a given category key.
I tried :
NSString *categoryKey = #"A";
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"categories.%K == YES", categoryKey]];
// or
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SELF.categories.%# == YES", categoryKey]];
// or
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"categories[%#] == YES", categoryKey];
// Throws exception : Unsupported function expression categories["A"]
// or
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"categories[%K] == YES", categoryKey];
// Throws exception : Unsupported function expression categories[A]
// or
NSString *categoryKeyPath = [NSString stringWithFormat:#"categories.%#", categoryKey];
NSPredicate *p = [NSPredicate predicateWithFormat:#"%K == YES", categoryKeyPath]];
But it always returns empty array when performing my fetch (of course I have some objects with categories[#"A"] = YES).
I think the problem comes from nested dictionary key path but I can't find a way to achieve this with one predicate.
Edit:
To clarify I would use
NSPredicate *predicate = [NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary *bindings) {
return [[evaluatedObject.categories objectForKey:categoryKey] boolValue];
}];
But predicateWithBlock: is not supported when fetching in core data.
If I understand correctly categories is a string attribute on your entity, which contains JSON data, and your managed objects parse this JSON so it can be read as a dictionary.
The problem is that the managed objects are not created before the fetch is performed. At that point, categories is just a string, and no key path will be able to extract the info you want from it. You will need to fetch all the objects so they can construct their dictionaries, then filter that collection. For large data sets, this may be slow.
Core Data is designed to be used by explicitly modelling the data; if you jam your own data structure inside a string, Core Data can’t help you. The more idiomatic design would be to have a Categories entity with a to-many/to-many relationship with the entity of your object. This makes it trivial to find all the objects in category A by fetching category A then following the relationship.
Try this
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SELF.categories LIKE \"%#\":true", categoryKey]];
EntityA has a to-many relationship to EntityB (and EntityB has a to-one relationship to EntityA). I have an array of EntityBs (or more accurately, I have an NSArray that contains instances of NSManagedObject which represent EntityB). I want to create an NSFetchRequest that will fetch all EntityAs that have a relationship to at least one of the EntityBs in the array. How do I write the predicate for this fetch request?
The following works, but I think it is sub-optimal; it's hard to grok and I'm sure there must be a better way of expressing this:
NSArray *entityBs = ...;
NSMutableArray *containsEntityBSubPredicates = [NSMutableArray new];
for (NSManagedObject *entityB in entityBs) {
[containsEntityBSubPredicates addObject:[NSPredicate predicateWithFormat:#"%# IN entityBs", entityB]];
}
NSPredicate *containsEntityBsPredicate = [NSCompoundPredicate orPredicateWithSubpredicates:containsEntityBSubPredicates];
I've also tried this, but it doesn't work:
NSArray *entityBs = ...;
NSPredicate *containsEntityBsPredicate = [NSPredicate predicateWithFormat:#"ANY %# in entityBs", entityBs];
Am I missing a simpler solution?
You were almost there with your predicate, just switch the parameters:
[NSPredicate predicateWithFormat:#"ANY entityBs in %#", entityBArray];
Look at Apple's example code with IN here for further explanation.
I'm working on an app where I have Post objects, each Post can have many Entities (mentions, hashtags and links), each Entity have one Post. I have one main class for Entity, then I have three subclasses.
Mention : Entity
My mention class have the following properties:
#property (nonatomic, retain) NSString * name;
#property (nonatomic, retain) NSNumber * userId;
I now want to create a NSPredicatethat finds all Posts that are mentioning a certain User and userId, and I'm not sure how I should do that.
I have tried some things like this:
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"ANY mentions.userId like %#", [Session currentUser].userId];
// That doesn't work since Post(s) have many entities and not Mention(s).
// I have also tried something like this:
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"ANY entities.mentions.userId like %#", [Session currentUser].userId];
// And that didn't work either.
Any ideas on how I best should find all posts that are mentioning a certain user with a specific userId?
Inheritance is there so you do not have to code equal attributes twice. Otherwise, managed objects with parent objects are just like other managed objects.
Therefore, you should give your posts three relationships:
Post
hashes Hash
mentions Mention
links Link
Then your problem becomes trivial:
[NSPredicate predicateWithFormat:#"ANY hashes.userID = %#", _currentUser.userID];
Like does not make sense, as userID is presumably unique, and LIKE is much more expensive than simple equivalence.
If you want just one to-many relationship to one class of entity you will have to include another attribute in Entity, e.g. an NSNumber, to indicate what type it is. The predicate would then be as follows, assuming you use an enum to make the number types more readable:
[NSPredicate predicateWithFormat:
#"ANY (entity.type == %# && entity.userID == %#)",
#(EntityTypeMention), _currentUser.userID];
Don't know if you got my question, so here is an example.
I have an array with 50 product IDs and I want to check if all IDs exist in Core Data. How would I do that without a loop and making 50 requests? There must be a more efficient way than that I think.
In my model I have an entity Product with just Name and Id attributes.
You can use...
[fetchRequest setPredicate:[NSPredicate predicateWithFormat: #"productid IN[c] %#", ids]];
where ids is an array of NSStrings and fetchRequest is you NSFetchRequest on the entity with the property productid.
You can also do this for other object types and for relationships.
i.e.
NSArray *requiredChildren = //some array of coredata objects
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"child IN %#", requiredChildren];