predicateWithFormat:argumentArray: Using all items in NSArray - core-data

- (void)filterViaCategories:(NSArray *)array {
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"(todo_category_id == %#)" argumentArray:array];
}
but when I have used:
po predicate
Result is:
todo_category_id == 41123..
It just using 41123 from zero index element of array
i want all categories from data base for all id present in array not the only object at index zero:
(todo_category_id == 41123, 41234, 33455) etc.
How can I do this?

Then you should not be using predicateWithFormat:argumentArray: and you need to change your format.
You want something like:
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"todo_category_id IN %#", array];

Related

Is a subquery needed for my nspredicate to work properly?

I have an array of custom objects that have beds (1,2,3), fireplace (yes or no), den (yes or no) and ceiling heights (9-11,11-14,14-16). I need to allow filtering based on any/all/none of the items being selected to filter by. So a user may want to see 1 & 2 beds, den, fireplace and 9-11 foot ceilings. Or just 1 & 2 beds. My current predicate works for some of these. But it doesn't match all - only some. I am thinking I need a subquery. How to create a nested(?) subquery based on an array of filters?
Right now, the user selects buttons and those are matched against Filters and I use those to create my predicate.
Current predicate
Filters is an array of keys and predicate strings like 'beds, 1' and 'ceilings, 9-11'
`NSMutableArray *subPredicates = [NSMutableArray array];
for (Filter*fil in filters) {
NSPredicate *unitsPredicate = [NSPredicate predicateWithFormat:#"%K == %#", fil.key, fil.predicate];
[subPredicates addObject:bedsPredicate];
}
NSPredicate *predicate = [NSCompoundPredicate andPredicateWithSubpredicates:subPredicates];
NSLog(#"homes: %#", [searchArray filteredArrayUsingPredicate:predicate]);
NSArray *ar = [searchArray filteredArrayUsingPredicate:predicate];
I'd like to allow someone to pick any of the criteria and return appropriate data.
Subqueries are used with to-many relationships. If you want to filter multiple values then the class of fil.predicate should be an array (or set) of values. The predicate format is %K IN %#, for example
for (Filter*fil in filters) {
NSPredicate *unitsPredicate;
if ([fil.predicate isKindOfClass:[NSArray class]])
unitsPredicate = [NSPredicate predicateWithFormat:#"%K IN %#", fil.key, fil.predicate];
else
unitsPredicate = [NSPredicate predicateWithFormat:#"%K == %#", fil.key, fil.predicate];
[subPredicates addObject:bedsPredicate];
}
NSPredicate *predicate = [NSCompoundPredicate andPredicateWithSubpredicates:subPredicates];
See Aggregate Operations in Predicate Programming Guide.

predicate subquery to return items by matching tags

I have a many-to-many relationship between two entities; Item and Tag. I'm trying to create a predicate to take the selectedItem and return a ranking of items based on how many similar tags they have. So far I've tried:
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SUBQUERY(itemToTag, $item, $item in %#).#count > 0", selectedItem.itemToTag];
Any other iterations that have failed. It currently only returns the selectedItem in the list. I've found little on Subquery. Is there a guru out there that can help me refine this?
Thanks in advance for the help!
Edited 9June
The good news is with Dan's code I'm able to populate the tableview with items! Unfortunately ranking numbers are 0.
Solution
I originally tried searching for tags by ID rather than name. Note the two predicate options in 'rankingExpressionDescriptionForTags:' I do not have unique identifier to my tags and use the second of the two options. Thanks Dan!
A predicate is only the beginning.
First take a look at THIS VERY similar question.
Assuming your model has an Item and Tag entities, related in a many-to-many relationship:
Item.tags <<-->> Tag.items
The answer:
- (NSExpressionDescription*) rankingExpressionDescriptionForTags:(NSSet*)tags
{
NSPredicate* p = [NSPredicate predicateWithFormat:#"SUBQUERY(tags,$t,$t IN %#).#count > 0",tags];
//if your tags are not unique (meaning you only like to match the names of tags)
//change the predicate to:
//p = [NSPredicate predicateWithFormat:#"SUBQUERY(tags,$t,$t.tagName IN %#).#count > 0",[tags valueForKey:#"tagName"]];
NSExpression* rankExpresion = [(NSComparisonPredicate*)p2 leftExpression];
NSExpressionDescription* rankExpDesc = [[NSExpressionDescription alloc] init];
rankExpDesc.name = #"ranking";
rankExpDesc.expression = rankExpresion;
rankExpDesc.expressionResultType = NSInteger64AttributeType;
return rankExpDesc;
}
- (NSExpressionDescription*) objectIDExpressionDescription
{
NSExpressionDescription* expDesc = [[NSExpressionDescription alloc] init];
expDesc.name = #"objectID";
expDesc.expressionResultType = NSObjectIDAttributeType;
expDesc.expression = [NSExpression expressionForEvaluatedObject];
return expDesc;
}
- (NSFetchRequest*) rankingRequestForItem:(NSManagedObject*)item
{
NSFetchRequest* r = [NSFetchRequest fetchRequestWithEntityName:#"Item"];
NSPredicate* p = [NSPredicate predicateWithFormat:#"SELF != %#",item.objectID];
r.resultType = NSDictionaryResultType;
r.propertiesToFetch = #[[self objectIDExpressionDescription],
[self rankingExpressionDescriptionForTags:[item mutableSetValueForKey:#"tags"]]];
r.predicate = p;
return r;
}
Note:
The resulting array contains dictionaries
(AFAIK) You will have to sort the resulting array in-memory after the fetch if you like to sort by ranking
You cannot use a fetched results controller to track changes in these objects
You can use a FRC to display these items

NSPredicate on nested object / NSSet to filter the result during NSFetchRequest

I want a simple predicate that returns me all the groups which have mode = 0 and the mode of the enrollments in the group = 0
To be precise i need a predicate to access the nested object properties.
Somehow a predicate like:
[NSPredicate predicateWithFormat:#"mode = 0 AND enrollments.Enrollment.mode = 0"]
the above predicate is wrong and obviously doesn't work.
EDITED:
I have given a go to the following predicate too but been unsuccessful.
[NSPredicate predicateWithFormat:#"mode = 0 AND ALL ( SUBQUERY(enrollments,$varEnrollment,$varEnrollment.mode = 0))"]
I need result which contains all groups that are active (group.mode = 0) AND with all enrollee's that are active (enrolles.mode = 0)
but for me this predicate doesn't work.
From your question and the comments I guess that you want
[NSPredicate predicateWithFormat:#"mode = 0 AND (ALL enrollments.mode = 0)"]
UPDATE
It seems that the ALL aggregate does not work. It throws
'NSInvalidArgumentException', reason: 'Unsupported predicate (null)'
as #yunas noticed. This has also been noticed previously, e.g.
Core Data, NSPredicate and to-many key
Crash using Aggregate Operation: "ALL" in a Core Data iOS Application
On the other hand, the ANY aggregate works just fine. So as a WORKAROUND, one can replace ALL with an equivalent ANY expression:
[NSPredicate predicateWithFormat:#"mode = 0 AND NOT(ANY enrollments.mode != 0)"];
And this actually works (I have tested it)!
UPDATE 2
During the discussion it has become clear that yunas wants to display a table with one row for each group with mode=0, and within the table row display all enrollments of that group with mode=0.
First solution (probably the better one): Find all admissible groups first with the method given above. For each row (in cellForRowAtIndexPath:) filter the enrollments for that group and draw the cell.
Second solution: Fetch all enrollments and sort them by group. This requires only one fetch request, but the result is not so suitable as table view data source. The fetch request would look like this:
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:#"Enrollment"];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"mode = 0 AND group.mode = 0"];
request.predicate = predicate;
NSSortDescriptor *sort1 = [NSSortDescriptor sortDescriptorWithKey:#"group.name" ascending:YES];
NSSortDescriptor *sort2 = [NSSortDescriptor sortDescriptorWithKey:#"share" ascending:YES];
request.sortDescriptors = [NSArray arrayWithObjects:sort1, sort2, nil];

How to write a NSPredicate to obtain all items whose ids are in an array?

In my core data db, every item has a string id which is an url to indicate whom this item belongs to.
Now I have an array which contains, say, 200 owner urls (200 is just an example, it is dynamic in the app). I wish to fetch all items that belong to the 200 own urls.
If only 1 owner url, I know how to write:
[NSPredicate predicateWithFormat:#"(ownerUrl == %#)", url]
What about an array of owner urls, say 200?
by the way, the core data I am using is sql. I think sql will ignore "IN" in NSPredicate?
Thanks
Try this :
NSSet *urls = [NSSet setWithObjects:#"url1", #"url2", #"url3", nil];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"%K IN %#", #"ownerUrl", urls];

CoreData - NSPredicate results if relationship has data

I have a many-to-many relationship between tables, and I populate a tableView with Activities.
For that i user a simple NSPredicate like this:
request.predicate = [NSPredicate predicateWithFormat:#"deleted == %#", [NSNumber numberWithBool:NO]];
How can I do to show only the Activities that has Members attached to it?
I think that in the NSPredicate I have to do some count so that only the Activities with count > 0 are returned. Is that so?
How?
(i'm newbie in coredata...)
Thanks,
RL
You need to add a subquery to your predicate acting on the CompanyActivity entity as follows:
[[NSPredicate predicateWithFormat:#"deleted == %#" && (0 >= SUBQUERY(Members, $sub, $sub.deleted == %#).#count)", [NSNumber numberWithBool:NO] [NSNumber numberWithBool:NO]];
The first part of the predicate returns objects which have not been deleted, the second one related to the subquery will take care of retrieving all those CompanyActivity objects whose Members have not been deleted.

Resources