2009-09-10 10 views
2

J'ai une entité "Song" et une entité "Tag" et ils ont une relation de plusieurs à plusieurs entre eux. Une chanson peut avoir plusieurs balises et une balise peut être appliquée à plusieurs chansons.Données de base: Comment vérifier la présence de plusieurs à plusieurs relation

Je souhaite vérifier si un tag est associé à un tag particulier. Si le morceau est associé à la balise, je veux afficher une coche dans la vue de la table.

Pour une logique similaire, dans l'exemple de code Apple "TaggedLocations", la vérification suivante est effectuée pour vérifier la présence de la relation.

if ([event.tags containsObject:tag]) { 
    cell.accessoryType = UITableViewCellAccessoryCheckmark; 
} 

Cela peut être inefficace s'il y a beaucoup de mots clés dans la base de données que cela va aller chercher tous dans la mémoire. Corrigez-moi si je me trompe ici.

Existe-t-il un moyen plus efficace de vérifier si le morceau est associé à un tag particulier au lieu de vérifier Song.Tags?

Répondre

5

C'est en fait assez facile à faire, si complètement non documenté. Vous voulez créer une requête d'extraction avec un prédicat ayant une opération set. Si l'on imagine que votre modèle de balise a une propriété appelée TAGVALUE, le prédicat que vous aimez est « TOUT tags.tagValue == « footag » »

NSString *tagSearch = @"footag"; 

// However you get your NSManagedObjectContext. If you use template code, it's from 
// the UIApplicationDelegate 
NSManagedObjectContext *context = [delegate managedObjectContext]; 

// Is there no shortcut for this? Maybe not, seems to be per context... 
NSEntityDescription *songEntity = [NSEntityDescription entityForName:@"Song" inManagedObjectContext:context]; 

NSFetchRequest *request = [[NSFetchRequest alloc] init]; 
[request setEntity:songEntity]; 

// The request looks for this a group with the supplied name 
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"ANY tags.tagValue == %@", tagSearch]; 
[request setPredicate:predicate]; 

NSError *error = nil; 
NSArray *results = [context executeFetchRequest:request error:&error]; 

[request release]; 
3

Vous avez raison, en utilisant ce code récupérera l'ensemble entier et la comparaison d'objet peut être assez complexe, selon combien de propriétés et de relation font partie de l'entité de l'objet.

De toute façon, vous ne pouvez pas éviter une comparaison d'ensemble pour l'inclusion. Probablement, le mieux que vous pouvez faire est d'éviter de récupérer toutes les propriétés/relations en demandant aux données de base de récupérer uniquement les objets NSManagedObjectID.

NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; 
[fetchRequest setEntity:[NSEntityDescription entityForName:@"Tag" inManagedObjectContext:[self managedObjectContext]]]; 
[fetchRequest setResultType:NSManagedObjectIDResultType]; 

objets NSManagedObjectID sont garantis pour être unique, donc vous pouvez en toute sécurité les utiliser pour vérifier l'inclusion ensembliste. Cela devrait être beaucoup plus efficace pour une perspective de performance.

+0

Merci pour l'explication. À mon humble avis, cela signifierait toujours récupérer et conserver tous les objets Tag associés en mémoire en même temps. Que faire s'il y a 1000 étiquettes associées dans la base de données? Dans mon implémentation actuelle de données non-core, j'ai une table de jointure intermédiaire pour vérifier la présence de l'association. Le document Données de base indique que les données de base prennent en charge la table de jointure intermédiaire pour les relations plusieurs à plusieurs. Existe-t-il un moyen d'écrire un prédicat pour utiliser les propriétés de la table de jointure intermédiaire et éviter de lire tous les objets dans la mémoire? – siasl

+0

Vous ne pouvez pas tirer parti de la table de jointure intermédiaire. Il est utilisé de manière transparente par Core Data. Un cas particulier est possible, dans lequel vous ajoutez explicitement une troisième entité intermédiaire entre les deux entités d'origine, comme décrit dans Apple "Core Data Programming Guide", section intitulée "Relations et propriétés récupérées", et dans cette section jetez un oeil à "Relations plusieurs-à-plusieurs". Vous devez décider si vos relations Songs/Tags peuvent être modélisées comme dans leur exemple d'amis (probablement pas). –

+0

Yeah Songs/Tags ne correspond pas vraiment à ce modèle, soupir! – siasl

Questions connexes