How do I filter CoreData results based on a relationship - core-data

I have a list of users, each with
Users.accounts--->Accounts.measurements--->measurement.account
I want to pull all measurements from the measurements "table" where measurement.account=a specific account, and where measurement.type (a property) is "wind speed" as an example.
So I:
Create a fetch request on measurements
I want to create a predicate that says type="wind speed" and account={NSAccount object}
How do I do this?
Measurement type is easy:
*predicate = [NSPredicate predicateWithFormat:#"measuretype = 'air speed'];
Specifying the relationship, I don't know:
myAccountObject *myAccount=[accountFromId:#"6785"];
*accountpredicate = [NSPredicate predicateWithFormat:#"account = ???",myAccount];

In a predicate, %# is a var arg substitution for an object value, so
[NSPredicate predicateWithFormat:#"account = %#",myAccount]
is probably what you are looking for. Even for a constant string this is preferable, because it avoids problems with embedded quotation marks or other special characters, which would
have to be quoted otherwise. So your combined predicate would be:
[NSPredicate predicateWithFormat:#"measuretype = %# AND account = %#",
#"air speed", myAccount]
For more information, see "Predicate Format String Syntax" in the
"Predicate Programming Guide".

Related

how to create compoundpredicate within nsFetchRequest that filters by two parameters of different entity

Some background info on my datamodel:
manufacturer <-->> item <<-->> tag
I currently generate a list of items by a fetchrequest:
- (NSFetchRequest*) rankingRequestForItem:(Item*)item {
NSFetchRequest* r = [NSFetchRequest fetchRequestWithEntityName:#"Item"];
NSPredicate* p = [NSPredicate predicateWithFormat:#"SELF != %#",item.objectID];
r.resultType = NSDictionaryResultType;
r.resultType = NSDictionaryResultType;
r.propertiesToFetch = #[[self objectIDExpressionDescription],#"itemName",
[self rankingExpressionDescriptionForTags:[item mutableSetValueForKey:#"itemToTag"]]];
r.predicate = p;
r.sortDescriptors = #[[NSSortDescriptor sortDescriptorWithKey:#"itemName" ascending:YES]];
return r;
}
This generates a list of all items. I want to filter it for items that have a relationship to a specific manufacturer. So I'm adding a predicate after the listing of all items and it sorts by selectedManufacturer.
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"itemToMa = %#", selectedManufacturer];
This works, but is grabbing a lot of items that will be filtered out. With large data sets I'm assuming will become slower and slower as it searches all items rather than just the ones associated with one manufacturer. I want to filter for items within the initial 'rankingRequestForItem' method.
Is it possible to move the above predicate with the top predicate and create a compoundpredicate?
I would not worry about performance. Core Data manages that pretty well under the hood. Sometimes the order of the predicates matters, so maybe put the manufacturer filter first.
You can combine the predicates in one as suggested in the comment to your question, or use compound predicates -- the result is pretty much the same.

Creating Core Data predicate to get data within one-to-many relationship

I have a Loans entity with a returnedDate attribute that can contain a date or be NIL. There is a to-many relationship with another entity, Items such that items can be related to many Loans. I would like to create a predicate where I can find all items that do not currently have a loans.returnedDate==NIL.
Assume I currently have the following:
Loan1-item1,returnedDate=NIL
Loan2-item1,returnedDate=5/4/2012
Loan3-item2,returnedDate=NIL.
I would like a predicate that returns no items.
NSPredicate *pred = [NSPredicate predicateWithFormat:#"!(ANY loaned.returnDate==nil)"];
Returns item1.
NSPredicate *pred = [NSPredicate predicateWithFormat:#"(NONE loaned.returnDate==nil)"];
Returns item1.
NSPredicate *pred = [NSPredicate predicateWithFormat:#"(ANY loaned.returnDate!=nil)"];
Returns item1.
Can someone tell me what logic would return the appropriate results?
So I used the following predicate:
(SUBQUERY(loaned, $sub, $sub.returnDate==nil).#count == 0)
and it is returning the desired results. If you can convince me not to use SUBQUERY, please tell me how.

Core Data NSPredicate casting key value

I have a data model which has values of type id that I was planning on casting appropriately when needed.
Is it possible for me to cast these as strings and compare them to strings from a UISearchBar using NSPredicate or do I have to use another method?
Maybe something like this:
NSPredicate * predicate;
predicate = [NSPredicate predicateWithFormat:#"CAST(%K) contains[cd] %#", employeeID , theSearchBar.text];
No. The CAST() function doesn't work that way. I think you just have to assume that the id returned from -employeeID is comparable to a string.

having problem with NSPredicate predicateWithFormat "OR"

I am trying to fetch an entity from coredata using NSPredicate. I am trying to do a 'search as you type' approach. It works fine on a simple product name like "chair" or "Table".
But as soon as I tried the more complicate stuff like "Wheelchair - electric - power" then when I type in "Wheelchair electric" the result is not showing. I think it has to do with my NSPredicate predicateWithFormat but I've been at this for awhile now. So I need some help.
Here is my code (these are my best guesses)
request.predicate = [NSPredicate predicateWithFormat:#" Name BEGINSWITH [c] %# ",searchText];
request.predicate = [NSPredicate predicateWithFormat:#" Name BEGINSWITH [c] %# OR Name like[cd] %# ",searchText,searchText];
Thanks in advance :)
Pondd
To have an OR search you will have to first split the search term by whitespace into an array. Then you need to create a LIKE predicate for each individual component. Finally you have to combine the individual predicates with several OR compound predicates.

How can I use NSPredicate to filter on core data relationships?

Say I have core data objects of type "obj" that has a property "propertyA" and a one-to-many relationship with an object of type "sub" that has two properties, "propertyB" and "propertyC".
I want to fetch all the objs that have propertyA equal to a value and a sub obj with propertyB and propertyC set.
If it was just propertyA and propertyB, I would do
[NSPredicate predicateWithFormat:#"ANY sub.propertyB = %# AND propertyA == %#", ...];
The problem is that I can't figure out how to add in the second property. I want only the objs that have at least one sub that has the two properties true. I've tried the following, but it doesn't work:
[NSPredicate predicateWithFormat:#"ANY (sub.propertyB = %# AND sub.propertyC) AND propertyA == %#", ...];
I've tried it without the ANY but that doesn't work either. How can I do this?
Since you have a to-many relationship with the sub object, the subs property of obj returns a set instead of a single object. To query the set, you need to use a SUBQUERY.
Subqueries have the form:
SUBQUERY(collection, $individualCollectionItem, expression-with-collection-item)
in this case you would want something like
SUBQUERY(subs,$s,$s.propertyB==%#) AND SUBQUERY(subs,$s,$s.propertyC!=NULL)
The solution seems to be:
[NSPredicate predicateWithFormat:#"propertyA == %# AND (SUBQUERY(sub, $s, $s.propertyB == %# AND $s.propertyC == %#).#count != 0)", propertyAvalue, propertyBvalue, propertyCvalue];
where the values at the end are the values you want the various properties to be equal to.

Resources