2016-03-12 8 views
6

Ho un NSPredicate che include più filtri aggregati, che genera un'eccezione.NSPredicate su più to-molti relazioni in Core Data

Ho il seguente modello di dati di base:

Core data model

voglio scegliere quelli ApparelItems per i quali una delle colours ha un rgb di 13.576.743, e per la quale tutti i picks avere un pickTime precedenza di un dato NSDate.

Il mio codice per creare il predicato è:

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) 

ottengo la seguente eccezione:

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

ho provato:

  1. Ogni predicato individuale funziona bene. Vale a dire ANY colours.rgb = ... opere, anche opere ALL picks.pickTime < .... Semplicemente non funzionano se combinati nella stessa query.

  2. Combinare i due utilizzando in una singola query, collegata a AND, anziché utilizzare NSCompoundPredicate. Il risultato è lo stesso.

È possibile che i dati di base semplicemente non supportino il filtraggio su più di una relazione to-many? Sembra strano. In tal caso come dovrei fare quanto sopra?

+0

Una possibile via d'uscita, a seconda della cardinalità delle tabelle nelle domande, sarebbe quella di effettuare il filtraggio più selettivo nei dati di base il secondo in memoria usando 'filteredArrayUsingPredicate' –

+0

Grazie ... d'accordo è possibile, ma è possibile sembra davvero inefficiente. Per prima cosa (anche se non è mostrato nel codice sopra, che è una versione semplificata) in realtà sto solo chiedendo i dati di base per il suo 'ManagedObjectId's. Quindi non ho effettivamente gli oggetti su cui lavorare. Di nuovo, è ovviamente qualcosa che potrei cambiare, ma l'ho fatto in questo modo per mantenere basso l'utilizzo della memoria. – HughHughTeotl

+0

hai provato a utilizzare la sottoquery? – Wain

risposta

2

Probabilmente si potrebbe provare SUBQUERY() per NSPredicate.

Il codice qui sotto è venuto fuori da qualche ipotesi e non molto sicuro se funziona o meno. Di solito sono necessarie numerose prove per una clausola di query to-many con NSPredicate.

var predicates = [NSPredicate]() 
predicates.append(NSPredicate(format: "SUBQUERY(colours, $colour, ANY $colour.rgb = 13576743)[email protected] > 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 < %@)[email protected] > 0", midnightXDaysAgo)) 
} 
+1

Sembra funzionare. Per riferimento ho solo bisogno di cambiare un predicato in una sottoquery. Così ho cambiato la data per 'predicates.append (NSPredicate (formato:" SUBQUERY (picks, $ pick, $ pick.pickTime>% @). @ Count = 0 ", midnightXDaysAgo))' (leggermente diverso da quello che avevi , ma lo stesso concetto.) Grazie per la risposta. – HughHughTeotl

0

I colori e le scelte sono due entità diverse, così si dovrebbe essere in grado di filtrare sia senza usare SUBQUERY. Un predicato o un predicato composto dovrebbero entrambi essere soddisfacenti.

Dal messaggio di errore sembra che forse qualcosa non va con la data. Verifica di avere il tipo di dati previsto nelle sottoclassi degli oggetti gestiti. Se si sono utilizzati "valori primitivi" durante la creazione delle sottoclassi, sarà necessario NSTimeInterval anziché NSDate.