objective c - fetch data (core data) - ios

I have two tables Photo and Photographer.
Below is the structure of the tables.
I'm trying to fetch the name of all Photographers who have taken a photo called "Panda".
Here's my code but for some reason it's returning empty.
NSArray *matchingPhotographers;
NSFetchRequest *fetch = [[NSFetchRequest alloc]init];
NSEntityDescription *desc = [NSEntityDescription entityForName:#"Photographer" inManagedObjectContext:context];
[fetch setEntity:desc];
[fetch setPredicate:[NSPredicate predicateWithFormat:#"photo.name like[c] %#",#"Panda"]];
NSError *error;
matchingPhotographers = [context executeFetchRequest:fetch error:&error];
NSLog(#"Photographers: %#", matchingPhotographers);
Am I doing something wrong? The query should definitely return at least 1 photographer.
Thanks

Photo is a collection, so your predicated must be:
[fetch setPredicate:[NSPredicate predicateWithFormat:#"ANY photo.name like[c] %#",#"Panda"]];
This predicate finds "Photographers" which have at list one photo (among his photo's collection) with the name like "Panda".

photo is a to-many relationship so it's easier to use a subquery predicate to count the photos in the relationship which match your criteria:
#"SUBQUERY(photo, $p, $p.name ==[c] %#).#count > 0", #"Photo"
Note I'm also not using LIKE so it isn't a regex comparison.

Related

Core Data: How to fetch Entities based on an attribute of a related entity

This is what the pertinent part of my object graph looks like:
[Anime] <->> [AnimeName #string #type]
So an Anime object has many AnimeName objects that contain a string and the type of name they are. Now to implement a "Search by Name" feature, I would need a predicate that matches all Anime entities where any name contains the search string. What I have tried so far is this:
NSFetchRequest *fetch = [NSFetchRequest fetchRequestWithEntityName:#"Anime"];
[fetch setPredicate:[NSPredicate predicateWithFormat:#"names.string == %#", searchString]];
on an NSFetchRequest of Anime entities, this however gives the following error:
"NSInvalidArgumentException", "to-many key not allowed here"
Which makes perfect sense to me, and I could simply work around that by using this:
NSFetchRequest *fetch = [NSFetchRequest fetchRequestWithEntityName:#"AnimeName"];
[fetch setPredicate:[NSPredicate predicateWithFormat:#"string == %#", searchString]];
and then getting the relationship to the Anime entity from each returned object, but then how do I plug that into an NSFetchedResultsController for my UITableView?
Please help if anyone knows a solution.
For to-many relationships, use "ANY":
NSFetchRequest *fetch = [NSFetchRequest fetchRequestWithEntityName:#"Anime"];
[fetch setPredicate:[NSPredicate predicateWithFormat:#"ANY names.string == %#", searchString]];

NSPredicate fetch coredata

I have two linked types in my CoreData model.
FlightRecording and AHRSMessage
One FlightRecording links to many AHRSMessages.
I've been fetching each recording and iterating through its linked messages:
for (__weak id msgObj in rec.ahrsMessages) {
and have not been seeing the performance I'd like. As I'm fetching the actual recording objects and not the messages I don't believe I can set a batch size on the fetch so I was thinking i'm better off fetching the messages using a correct predicate format.
Assuming I have a NSManagedObjectID for my flight recording is there a quick way to do a predicate query on my AHRSMessage
I've gotten this far which isn't that far:
NSFetchRequest *msgFetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"AHRSMessage" inManagedObjectContext:context];
And then i wasn't sure what to do for my predicate. Do I have to match on an actual field such as:
"ANY flightRecordings = %#" or something like that?
Do I have to reference a specific field in flightRecording or is there a way to just match on the ID?
If "flightRecordings" is a to-many relationship from the AHRSMessage entity to
FlightRecording then this should work:
NSManagedObjectID *flightRecordingId = ...;
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:#"AHRSMessage"];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"ANY flightRecordings = %#", flightRecordingId];
[fetchRequest setPredicate:predicate];
The argument of the "ANY flightRecordings = %#" predicate can be a FlightRecording object or a NSManagedObjectID of a FlightRecording object.

Core Data fetching relationship objects

in my app i have two entities: Members and Lists. they both have a one-to-many relationships (member can have more than one list, list can have more than one member). now i want to fetch the lists belonging to a specific member. here is my code:
WSAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
NSManagedObjectContext *context = [appDelegate managedObjectContext];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Lists" inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSPredicate *predicate = [NSPredicate predicateWithFormat:[NSString stringWithFormat:#"has_members contains[cd] %#", [self.currentMember valueForKey:#"name"]]];
[fetchRequest setPredicate:predicate];
NSError *error;
NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:&error];
if (fetchedObjects == nil) {
// Handle the error.
NSLog(#"NO LISTS AVAILABLE IN REFRESH");
}
self.currentMember is a managed object of the user himself.
Note: member has name, (NSSet*) member_of_list
list has list_name, has-members
Problem: when i run the code it's breaking at the fetchedObjects array. i suspect that there is something wrong with the NSPredicate but i don't know where and how to fix it. can any one point out the problem?
First, the relationship you describe between Member (Calling an entity in a plural form is confusing) and List is many-to-many.
Second, instead of using CoreData's inherent object graph capabilities, you went and "rolled your own" relationship between the entities (you should use your interface builder to model a CoreData relationship between the two entities).
See HERE how to do that.
after you model your data, your predicate should look something like:
//Not tested
NSPredicate* p = [NSPredicate predicateWithFormat:#"ANY members = %#",self.currentMember];
DO NOT pass a formatted string to create the predicate, use NSPredicate formatting to substitute parameters or you will not be able to accomplish your goal (in most cases).

Fetchrequest with NSPredicate not returning right values

I'm having a strange problem with Core Data.
The problem is that I'm looking for objects with a property less than X and it isn't returning all the values that matches.
There is no cache and I'm not using //[fetchRequest setFetchBatchSize:50];
NSPredicate *pred = [NSPredicate predicateWithFormat:#"self.level <= [cd] %#", [self.filters objectForKey:#"level"]];
I add it to a MutableArray of predicates and later I execute
NSPredicate *myPredicate = [NSCompoundPredicate andPredicateWithSubpredicates: subPredicates];
This one it's in a function that returns myPredicate called preparePredicates. For the moment there aren't more predicates, only one.
It's NSLog returns: level <=[cd] "30".
I have tried it also with intValue of the string and %i
The main function:
NSError* error;
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"myEntity"
inManagedObjectContext:self.context];
[fetchRequest setEntity:entity];
NSPredicate* predicate = [self preparePredicates];
[fetchRequest setPredicate:predicate];
//[fetchRequest setFetchBatchSize:50];
NSArray *fetchedObjects = [self.context executeFetchRequest:fetchRequest error:&error];
NSLog (#"Error: %#", error);
NSLog(#"los fetchedobjects: %i",[fetchedObjects count]);
return fetchedObjects;
It doesn't return any error.
If I look at the results there isn't one having a level of 6, but there are others that matches (all are less than the specified). I know there is one with level 6.
If I open the .sqlite in SQLite Database Browser, I can see it there.
If I do with this program a
SELECT * FROM zmyentity WHERE zlevel <30;
it doesn't appear, same as in Core Data do. But if I do a
SELECT * FROM zmyentity WHERE zlevel == 6;
it appears.
I really don't know what is happening. Maybe I'm making a rookie mistake, so please point me in the right direction.
Thank you very much in advance.
Probably you have stored the level as a String attribute, because
"30" < "6"
when comparing strings. Choosing a numeric attribute type (Integer 16/32/64) should solve the problem. The corresponding level property in the myEntity class has then the NSNumber type.
You should also omit the [cd] modifier in the predicate, because that enforces a string comparison.
You predicate could then look like this:
[NSPredicate predicateWithFormat:#"self.level <= %d", [[self.filters objectForKey:#"level"] intValue]]

NSPredicate, get results with a subset of one-to-many relationship

I'mm working around with Core Data and NSFetchedResultsController.
My Data Model looks like this:
Product with one-to-many relationship called dataLines.
The dataLine entity has a property name theWeek.
I want to fetch all Product where dataLines.theWeek == someValue. This is easily done with a subquery. But this returns all dataLines. Is it possible to create a NSPredicate that returns the Product and a subset if dataLines only with the dataLines == someValue?
What you want to achieve could be reached in two ways:
using a SUBQUERY
[NSPredicate predicateWithFormat:#"SUBQUERY(dataLines, $x, $x.theWeek == %#).#count > 0)", [NSNumber numberWithInt:18]];
or the ANY modifier
[NSPredicate predicateWithFormat:#"ANY dataLines.theWeek == %#", [NSNumber numberWithInt:18]];
You can do also the following if you need to check against multiple values:
[NSPredicate predicateWithFormat:#"SUBQUERY(dataLines, $x, $x.theWeek == %# or $x.theWeek == %#).#count > 0)", [NSNumber numberWithInt:18], [NSNumber numberWithInt:19]];
The same can be applied to ANY modifier. ANY ... OR ANY ....
Maybe if you share some code we could help you.
P.S. I suppose you don't use scalar values and theWeek is a number.
Hope it helps.
You should fetch the dataLine property instead.
Assuming your Product and dataLine entity connected by relationship someRelation then you can try this code;
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
[fetchRequest setEntity:[NSEntityDescription entityWithName:#"dataLine" inManagedObjectContext:self.managedObjectContext]];
[fetchRequest setPredicate:[NSPredicate predicateWithFormat:#"dataLines.week == %#",theWeek]];
NSMutableArray *tmpProduct [[NSMutableArray init] alloc];
NSMutableArray *tmpArray = [self.managedObjectContext executeFetchRequest:fetchRequest error:&error];
for (dataLine *theDataLine in tmpArray);
NSLog(#"%#",theDataLine.someRelation.name);
tmpProduct = theDataLine.someRelation.name;
then you can just call tmpProduct to call or display your product in table view
Create a fetch request for the 'Product' entity:
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
[fetchRequest setEntity: [NSEntityDescription entityForName:#"Product" ...]]
then create a predicate using the properties/attributes of Product with 'ANY':
[fetchRequest setPredicate:
[NSPredicate predicateWithFormat:#"ANY dataLines.theWeek == %#", <whatever week>]];
then execute the fetch to get an array of Product with at least one <whatever week>.
Generally see 'Fetching Managed Objects', NSPredicate and related documentation.

Resources