Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NSPredicate on multiple to-many relationships in Core Data

I have an NSPredicate which includes multiple aggregate filters, which is throwing an exception.

I have the following core data model:

Core data model

I want to pick those ApparelItems for which any of the colours has an rgb of 13576743, and for which all of the picks have a pickTime earlier than a given NSDate.

My code to create the predicate is:

let request = NSFetchRequest(entityName: "ApparelItem")
var predicates = [NSPredicate]()

predicates.append(NSPredicate(format: "ANY colours.rgb = 13576743"))

// find the NSDate representing midnight x days ago
let cal = NSCalendar.currentCalendar()
if let xDaysAgo = cal.dateByAddingUnit(.Day, value: -2, toDate: NSDate(), options: [])
{
    let midnightXDaysAgo = cal.startOfDayForDate(xDaysAgo)

    predicates.append(NSPredicate(format: "(ALL picks.pickTime < %@)", midnightXDaysAgo))
}

request.predicate = NSCompoundPredicate(andPredicateWithSubpredicates: predicates)

let searchData = try? objectContext.executeFetchRequest(request)

I get the following exception:

Exception name=NSInvalidArgumentException, reason=Unsupported predicate (ANY colours.rgb == 13576743) AND ALL picks.pickTime < CAST(479347200.000000, "NSDate")

I have tried:

  1. Each individual predicate works fine. Ie ANY colours.rgb = ... works, also ALL picks.pickTime < ... works. They just don't work when combined into the same query.

  2. Combining the two using into a single query, linked with AND, rather than using NSCompoundPredicate. Result is the same.

Is it possible that core data simply doesn't support filtering on more than one to-many relationship? That would seem odd. In which case how should I do the above?

like image 247
HughHughTeotl Avatar asked Mar 12 '16 21:03

HughHughTeotl


1 Answers

Probably could try SUBQUERY() for NSPredicate.

The code below I came out from some guess and not very sure if it works or not. Usually it takes me trial and error many times for a to-many query clause with NSPredicate.

var predicates = [NSPredicate]()
predicates.append(NSPredicate(format: "SUBQUERY(colours, $colour, ANY $colour.rgb = 13576743).@count > 0"))
let cal = NSCalendar.currentCalendar()
if let xDaysAgo = cal.dateByAddingUnit(.Day, value: -2, toDate: NSDate(), options: []) {
    let midnightXDaysAgo = cal.startOfDayForDate(xDaysAgo)
    predicates.append(NSPredicate(format: "SUBQUERY(picks, $pick, ALL $pick.pickTime < %@).@count > 0", midnightXDaysAgo))
}
like image 95
Allen Avatar answered Oct 26 '22 03:10

Allen