2010-11-26 9 views
3

Meine App intelligente Ordner wie Funktionalität hat: ein Prädikat ist Setup mit einem NSPredicateEditor und verwendet, um den Ordner mit einer Abrufanforderung zu füllen.Core Data auf den Eigenschaften von ‚geordneten‘ Beziehungen auf der Grundlage holt

Die bei der Suche verwendet Unternehmen hat eine n-Beziehung. Die Beziehung ist geordnet in dem Sinne, dass ein Index in der Zieleinheit für Sortierzwecke gespeichert ist.

Mein Problem ist, dass ich eine Regel basierend auf den letzten Werten in der geordneten Beziehung einbauen möchte, aber ich kann nicht herausfinden, wie man ein Prädikat dafür erstellt, weil die Beziehung kein Array ist. Core-Daten wissen nicht wirklich über die Bestellung.

Ich habe eine Nur-Lese-Eigenschaft auf der Klasse, die die bestellten Artikel zurückgibt, aber dies scheint nicht mit der Abrufanforderung zu helfen, weil die Immobilie im Kerndatenspeicher nicht verfügbar ist.

Die einzige Option, die ich denken kann, ist de-normalisiert und speichern Sie die letzten Elemente in der Beziehung in einem separaten Objekt bestellt. Ist das die einzige Lösung?

Antwort

1

Ich glaube nicht, dass es eine Möglichkeit gibt, auf n Ergebnisse in einem Prädikat zu begrenzen, nur auf Abruf Anforderungsebene.

Abgesehen von den letzten n Elementen in einer Beziehung, wie Sie erwähnt haben, könnten Sie ein boolesches Attribut "lastN" versuchen und sie ein-/ausschalten, wenn Sie die Reihenfolge der Liste (z. B. während benutzerinitiierter Sortierung oder Drag & Drop-Neuordnung).

Alternativ können Sie eine separate Abrufanforderung für jede gesuchte Sache erstellen, die nach dem Sortierschlüssel sortiert wird, absteigend sortiert wird und (über -setFetchLimit:) auf n Ergebnisse beschränkt ist.

Verfolgen Sie dies als eine Beziehung oder ein Attribut ist etwas "chaotisch", während die Abrufgrenze teurer ist (wegen mehrerer Rundreisen). Wenn Ihre Neuanordnung durch einmalige Benutzeraktionen erfolgt, ist es möglicherweise leistungsmäßig sinnvoller, die Beziehung oder den Attributansatz zu verwenden, da die Arbeit in einer Abfolge von Abrufen auf einmal amortisiert und nicht auf einmal ausgeführt wird. Ich habe selbst keinen besseren Weg gefunden und werde diesen genau verfolgen. :-)

+0

Ich hatte gehofft, dass ich es mit einem einzigen Prädikaten erreichen könnte, aber ich fange an zu denken, dass es nicht getan werden kann. Ich habe das Gefühl, dass die Verwendung von zusätzlichen Eigenschaften - Denormalisierung - wahrscheinlich der beste Weg ist, auch in Bezug auf die Leistung. –

+0

Sicherlich ist die Methode der Suche nach einem Objekt durchsucht für eine große Liste von gesuchten Objekten schrecklich verschwenderisch und unvernünftig, aber für kleine Listen kann es ein angemessener Treffer sein. Ich würde persönlich den Ansatz "lastN" verwenden.Ich denke (aber zitieren Sie mich nicht) Beziehungen bedeuten automatisch mehrere Rundreisen mit Core Data. –

2

Nun, vorausgesetzt, ich das Problem richtig verstanden habe, würde ich es so machen. Nehmen wir an, Sie haben zwei Entitäten, TopEntity hat eine (NSString *) name-Eigenschaft und eine to-many-Beziehung zu MyEntity, die eine (NSString *) -Dateneigenschaft und (NSInteger) -Ordereigenschaft hat.

Lassen Sie uns sagen Sie die TopEntity Objekte wollen, die eine bestimmte Zeichenkette übereinstimmen, und deren MyEntity Aufträge sind eine bestimmte Bedingung erfüllen, dann können Sie es mit zwei Prädikate tun und ein NSFetchRequest wie so ....

NSManagedObjectContext *context = [self managedObjectContext]; 

// Create some top level entities 
TopEntity *aTop = [TopEntity insertInManagedObjectContext:context]; 
aTop.name = @"This is Your Name"; 
TopEntity *bTop = [TopEntity insertInManagedObjectContext:context]; 
bTop.name = @"This aint a Name";  
TopEntity *cTop = [TopEntity insertInManagedObjectContext:context]; 
cTop.name = @"This is My Name";  

// Add some data 
NSInteger i, len = 30; 
for(i=0; i<len; i++) { 
    // Create a new object 
    MyEntity *entity = [MyEntity insertInManagedObjectContext:context]; 
    entity.orderValue = i; 
    entity.data = [NSString stringWithFormat:@"This is some data: %d", i]; 
    if(i < 10) { 
     [aTop addObjectsObject:entity]; 
     [entity addTopObject:aTop]; 
    } else if (i < 20) { 
     [bTop addObjectsObject:entity]; 
     [entity addTopObject:bTop];    
    } else { 
     [cTop addObjectsObject:entity]; 
     [entity addTopObject:cTop];       
    } 
} 

// Save the context 
NSError *error = nil; 
[context save:&error]; 

// A predicate to match against the top objects 
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name BEGINSWITH %@", @"This is"]; 
// A predicate to match against the to-many objects 
NSPredicate *secondPredicate = [NSPredicate predicateWithFormat:@"ANY objects.order < %d", 5]; 
NSFetchRequest *fetch = [[NSFetchRequest alloc] init]; 
[fetch setEntity:[NSEntityDescription entityForName:@"TopEntity" inManagedObjectContext:context]]; 
[fetch setPredicate:predicate]; 
NSArray *result = [[context executeFetchRequest:fetch error:&error] filteredArrayUsingPredicate:secondPredicate]; 


for(TopEntity *entity in result) { 
    NSLog(@"entity name: %@", entity.name);   
} 

Im Wesentlichen können Sie also einfach die Ergebnisse Ihrer Abrufanforderung mit einem anderen Prädikat umbrechen und das Schlüsselwort ANY verwenden.

Ich habe keine Ahnung, wie effizient das ist, aber es funktioniert für diesen Fall. Wenn Sie den obigen Befehl ausführen, wird "Dies ist Ihr Name" ausgegeben, d. H. Es entspricht der ersten TopEntity.

+0

Ich bin nicht sicher, warum ich nicht darüber nachgedacht habe, aber es ist noch einfacher. Verwenden Sie einfach ein Prädikat mit einem Format wie @ "(name BEGINSWITH% @) UND (ANY objects.order>% d)". Die Gleichheit der Eigenschaft order hängt davon ab, was Sie wollen. Ich bin mir nicht sicher, ob Sie das Ergebnis basierend auf den Daten des Objekts n-recent to-many oder nur auf den Objekten n-recent einschränken möchten. Ich finde die NSPredicate-Formatzeichenfolge docs ziemlich nützlich: http://developer.apple.com/library/mac/#documentation/cocoa/Conceptual/Predicates/Articles/pSyntax.html%23//apple_ref/doc/uid/ TP40001795-CJBDBHCB –

+0

Hmm, die letzte Lösung der Verwendung des Orderindex ist eigentlich ziemlich gut. Könnte sicherlich für ein paar Fälle funktionieren, die ich habe. Vielen Dank! Die ursprüngliche Lösung war ebenfalls gut, passte aber nicht sehr gut zu meinem generischen "Smart Folder" -Ansatz, nach einem einzelnen Prädikat zu suchen. –

Verwandte Themen