2010-09-05 3 views
6

Hier ist das Modell, das ich habe: http://www.girardet.ch/model.pngCore Data, versuchen NSPredicate zu verwenden, um eine Tomany Beziehung gesetzt zu filtern, sondern erhalten, ist die „to-many-Schlüssel nicht erlaubt hier“ Fehler

Mein Ziel ist es, alle Zitate abrufen mit diesen Kriterien auf:

  • gehören zu einem bestimmten Thema: das name_en Attribut Themen
  • Reihenfolge nach Relevanz
  • von Autoren gefiltert (mit dem Alias-Attribute von Autoren)

Hier ist mein Code:

NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; 
NSEntityDescription *entity = [NSEntityDescription entityForName:@"ThemeEntries" inManagedObjectContext:_context]; 
[fetchRequest setEntity:entity]; 

NSSortDescriptor *sortDescriptor1 = [[NSSortDescriptor alloc] initWithKey:@"relevancy" ascending:NO]; 
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor1, nil]; 
[fetchRequest setSortDescriptors:sortDescriptors]; 

// predictate - filter 
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"theme.name_en=%@ AND quotes.author.alias=%@",@"mytheme", @"myauthor"]; 

[fetchRequest setPredicate: Prädikat];

Ich bekomme den "zu viele Schlüssel nicht erlaubt hier" Fehler.

Wenn ich stattdessen dieses Prädikat verwenden

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"theme.name_en=%@, @"mytheme"]; 

es gut funktioniert und ich kann Schleife über die ThemeEntries, die ich bekommen und erhalten Sie alle meine Zitate ... Aber es ist nicht von Autoren gefiltert.

Was kann ich tun, um nach Autoren zu filtern?

Antwort

26

Ihr Problem besteht darin, dass die Beziehung eines Ihrer Schlüsselpfade ein To-Many, To-Many ist und das Prädikat nicht weiß, welches bestimmte Objekt zu welchem ​​gehört.

Sie haben ThemeEntities<<-->>Quotes, die einen Satz an jedem Ende produziert. Der Schlüsselpfad quotes.author.alias sagt "eine Menge von Anführungszeichen-Instanzen, von denen jede mit Autoreninstanzen verknüpft ist, die wiederum ein Alias-Attribut haben." Das Prädikat kann die Menge nicht verarbeiten.

Sie müssen eine Unterabfrage verwenden, um einen zu vielen Schlüsselpfad zu überspringen. Die Unterabfrage ist im Wesentlichen ein verschachteltes Prädikat, das eine Menge durchsucht und eine weitere Menge von Objekten zurückgibt, die mit dem verschachtelten Prädikat übereinstimmen. Unterabfragen sind schlecht dokumentiert, aber sie haben die Form:

SUBQUERY(collectionName,$collectionElementVariable,expression-with-$collectionElementVariable) 

In diesem Fall sind Sie für alle Kurs Instanzen suchen, die einen Autor Beziehung mit einem Alias ​​den mitgelieferten String-Matching hat. Ihr Prädikat müsste so aussehen:

@"theme.name_en=%@ AND (0!=SUBQUERY(quotes,$eachQuote,$eachQuote.author.alias=%@)[email protected])",@"mytheme", @"myauthor" 

Die Unterabfrage sagt: „Von den Satz zitiert, nehmen jedes Zitat Objekt und testen, ob sein Autor Beziehung Objekt einen Alias-Attribut hat passende‚myauthor‘Zähle die Anzahl der. zitieren Sie Objekte mit dieser Übereinstimmung. Wenn die Zahl nicht Null ist, geben Sie TRUE zurück. "

Sie müssen Unterabfragen verwenden, wenn Sie einen Schlüsselpfad über eine Zu-Viele-Beziehung führen.

+0

Vielen Dank für diese großartige Antwort. Ich wusste nichts von den Unterabfragen und es ist definitiv sehr hilfreich. In meinem Fall wollte ich jedoch die Menge der Anführungszeichen, die von der Anfrage zurückgegeben wurden, "innerhalb" aller ThemeEntries filtern. Die Verwendung der Unterabfrage kann die zurückgegebenen Einträge filtern und sicherstellen, dass sie über die zugehörigen Zitate eine Beziehung zum Autor haben. Was ich schließlich getan habe, ist, ALLE Zitate zu bekommen, die mit dem Thema zu tun haben, ohne den Autor zu filtern und sie danach zu filtern.Aber ich frage mich immer noch, ob es einen Weg gibt, es direkt in der Anfrage zu tun (wie ein linker Join in sql). – Ben

+0

Nicht genau, was Sie suchen, aber das obige Prädikat sucht nur jene 'Quote'-Instanzen, die mit bestimmten 'verknüpft sind ThemeEntities Instanzen. Aufgrund der Bewertung von Prädikaten werden nur die "Quote" -Instanzen für "ThemeEntities" überprüft, die den ersten Test bestehen. – TechZen

+0

Vielen Dank für die Lösung dieses @TechZen !!! Verdammt, ich habe mich stundenlang damit herumgeschlagen und versucht, einen Weg zu finden, ein zusammengesetztes Prädikat zu erstellen, das einen Filter anwendet, der zwei Kriterien für dasselbe Collection-Element verwendet. Das war unglaublich einfach mit Hilfe Ihrer Antwort. Vielen Dank! –

Verwandte Themen