2009-06-02 8 views
32

Estoy buscando un conjunto de objetos de un almacén persistente de datos centrales utilizando una solicitud de recuperación y un predicado. Mi predicado actual simplemente verifica si un atributo es> = cierto valor. Todo esto funciona muy bien, excepto que quiero finalmente excluir cualquier objeto que se encuentre actualmente en una matriz.Datos principales: ¿Query ID de objeto en un predicado?

Básicamente necesito poder excluir un conjunto de objetos, y la única forma en que creo que puedo hacer esto es poder obtener una lista de objectID de mi matriz de objetos administrados, y crear otra expresión en mi predicado para asegurarse de que los objetos devueltos no tengan el mismo objectID. ES DECIR. @"ANY records.objectID NOT IN %@", arrayOfObjectID.

¿Cómo puedo hacer esto?

Respuesta

64

Un predicado como

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"NOT (self IN %@)", arrayOfExcludedObjects]; 

cuando la entidad de la solicitud de búsqueda es la entidad de objetos de la matriz, debe hacer lo que quiera. Esto puede, por supuesto, combinarse con otras cláusulas en un solo predicado para una solicitud de obtención.

En general, las comparaciones de objetos (por ejemplo, self == %@ o self IN %@) se comparan en objectID en las consultas de Core Data. El argumento puede ser una instancia de NSManagedObject o una instancia de NSMangedObjectID. Por lo tanto, el formato de predicado anterior podría tomar arrayOfExcludedObjects o [arrayOfExcludedObjects valueForKey:@"objectID"] como argumento.

+1

Tha Necesita su ayuda. Intenté usar [NSPredicate predicateWithFormat: @ "self NOT IN% @", myArrayOfManagedObjects], pero seguí recibiendo el error "No se pudo analizar el error de cadena de formato" self NOT IN% @ "en el tiempo de ejecución. ¿Algunas ideas? –

+0

Lo siento .. mi error por no probar antes de publicar. He corregido mi respuesta (use "NOT (self IN% @)" en lugar de "self NOT IN% @"). –

+0

Esto funcionó bien para mí. Lo usé para filtrar usando lógica compleja que no es compatible con SQL. Pero predicateWithBlock no funciona (por razones razonables) en SQL. –

9

Si bien la respuesta de @BarryWark es correcta cuando se trabaja con solicitudes de búsqueda, quiero escribir una advertencia a las personas que intentarán aplicar esta regla a un filtro de datos básicos para muchas relaciones.

Poco: Si la hora de filtrar a-muchas relaciones que utiliza un predicado y su matriz de objetos para IN consulta es un conjunto de ObjectID - entonces debe usar self.objectID en la cadena de consulta como

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(self.objectID IN %@)", arrayOfObjectIDs]; 

Dado que usar solo (self IN %@) en el caso de filtrar a muchas relaciones dará como resultado resultados incorrectos, es solo un NSArray que evalúa predicados y no sabe nada acerca de las cosas NSManagedObjectID de Core Data.

He creado un código de prueba especial que muestra esto. Perdón por tantas líneas, pero valen la pena. Hay dos entidades: usuario y publicación, y el usuario tiene una relación de muchos llamada "publicaciones".

User *user = [NSEntityDescription insertNewObjectForEntityForName:NSStringFromClass([User class]) inManagedObjectContext:managedObjectContext()]; 

Post *post = [NSEntityDescription insertNewObjectForEntityForName:NSStringFromClass([Post class]) inManagedObjectContext:managedObjectContext()]; 

[user addPostsObject:post]; 

[managedObjectContext() save:nil]; 

// 1. Both filtered relationship array and fetch result are correct! 
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(self IN %@)", @[ post ]]; 

NSSet *filteredRelationship = [user.posts filteredSetUsingPredicate:predicate]; 

NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:@"Post"]; 
NSArray *fetchResult = [managedObjectContext() executeFetchRequest:fetchRequest error:nil]; 

NSLog(@"\n\n\nPredicate: %@", predicate); 
NSLog(@"filteredRelationship: %@", filteredRelationship); 
NSLog(@"fetchResult: %@", fetchResult); 

// 2. Filtered relationship array is empty (wrong), fetch result is correct, ! 
predicate = [NSPredicate predicateWithFormat:@"(self IN %@)", @[ post.objectID ]]; 

filteredRelationship = [user.posts filteredSetUsingPredicate:predicate]; 

fetchRequest = [[NSFetchRequest alloc] initWithEntityName:@"Post"]; 
fetchResult = [managedObjectContext() executeFetchRequest:fetchRequest error:nil]; 

NSLog(@"\n\n\nPredicate: %@", predicate); 
NSLog(@"filteredRelationship: %@", filteredRelationship); 
NSLog(@"fetchResult: %@", fetchResult); 

// 3. Filtered relationship array is empty (wrong), fetch result is correct 
predicate = [NSPredicate predicateWithFormat:@"(self.objectID IN %@)", @[ post ]]; 

filteredRelationship = [user.posts filteredSetUsingPredicate:predicate]; 

fetchRequest = [[NSFetchRequest alloc] initWithEntityName:@"Post"]; 
fetchResult = [managedObjectContext() executeFetchRequest:fetchRequest error:nil]; 

NSLog(@"\n\n\nPredicate: %@", predicate); 
NSLog(@"filteredRelationship: %@", filteredRelationship); 
NSLog(@"fetchResult: %@", fetchResult); 

// 4. Filtered relationship array is correct, fetch result is correct 
predicate = [NSPredicate predicateWithFormat:@"(self.objectID IN %@)", @[ post.objectID ]]; 

filteredRelationship = [user.posts filteredSetUsingPredicate:predicate]; 

fetchRequest = [[NSFetchRequest alloc] initWithEntityName:@"Post"]; 
fetchResult = [managedObjectContext() executeFetchRequest:fetchRequest error:nil]; 

NSLog(@"\n\n\nPredicate: %@", predicate); 
NSLog(@"filteredRelationship: %@", filteredRelationship); 
NSLog(@"fetchResult: %@", fetchResult); 

salida TLDR

<redacted> Predicate: SELF IN {<Post: 0x2a04f10> (entity: Post; id: 0x2a56c40 <x-coredata://9D07BF41-2DC0-42C1-9DD8-6082A00E7BEB/Post/p1> ; data: { content = nil; title = nil; user = "0x2af2a20 <x-coredata://9D07BF41-2DC0-42C1-9DD8-6082A00E7BEB/User/p1>"; })} 

<redacted> filteredRelationship: {(<Post: 0x2a04f10> (entity: Post; id: 0x2a56c40 <x-coredata://9D07BF41-2DC0-42C1-9DD8-6082A00E7BEB/Post/p1> ; data: { content = nil; title = nil; user = "0x2af2a20 <x-coredata://9D07BF41-2DC0-42C1-9DD8-6082A00E7BEB/User/p1>"; }))} 

<redacted> fetchResult: ("<Post: 0x2a04f10> (entity: Post; id: 0x2a56c40 <x-coredata://9D07BF41-2DC0-42C1-9DD8-6082A00E7BEB/Post/p1> ; data: {\n content = nil;\n title = nil;\n user = \"0x2af2a20 <x-coredata://9D07BF41-2DC0-42C1-9DD8-6082A00E7BEB/User/p1>\";\n})") 

<redacted> Predicate: SELF IN {0x2a56c40 <x-coredata://9D07BF41-2DC0-42C1-9DD8-6082A00E7BEB/Post/p1>} 

<redacted> filteredRelationship: {()} 

<redacted> fetchResult: ("<Post: 0x2a04f10> (entity: Post; id: 0x2a56c40 <x-coredata://9D07BF41-2DC0-42C1-9DD8-6082A00E7BEB/Post/p1> ; data: {\n content = nil;\n title = nil;\n user = \"0x2af2a20 <x-coredata://9D07BF41-2DC0-42C1-9DD8-6082A00E7BEB/User/p1>\";\n})") 

<redacted> Predicate: objectID IN {<Post: 0x2a04f10> (entity: Post; id: 0x2a56c40 <x-coredata://9D07BF41-2DC0-42C1-9DD8-6082A00E7BEB/Post/p1> ; data: { content = nil; title = nil; user = "0x2af2a20 <x-coredata://9D07BF41-2DC0-42C1-9DD8-6082A00E7BEB/User/p1>";})} 

<redacted> filteredRelationship: {()} 

<redacted> fetchResult: ("<Post: 0x2a04f10> (entity: Post; id: 0x2a56c40 <x-coredata://9D07BF41-2DC0-42C1-9DD8-6082A00E7BEB/Post/p1> ; data: {\n content = nil;\n title = nil;\n user = \"0x2af2a20 <x-coredata://9D07BF41-2DC0-42C1-9DD8-6082A00E7BEB/User/p1>\";\n})") 

<redacted> Predicate: objectID IN {0x2a56c40 <x-coredata://9D07BF41-2DC0-42C1-9DD8-6082A00E7BEB/Post/p1>} 

<redacted> filteredRelationship: {(<Post: 0x2a04f10> (entity: Post; id: 0x2a56c40 <x-coredata://9D07BF41-2DC0-42C1-9DD8-6082A00E7BEB/Post/p1> ; data: { content = nil; title = nil; user = "0x2af2a20 <x-coredata://9D07BF41-2DC0-42C1-9DD8-6082A00E7BEB/User/p1>";}))} 

<redacted> fetchResult: ("<Post: 0x2a04f10> (entity: Post; id: 0x2a56c40 <x-coredata://9D07BF41-2DC0-42C1-9DD8-6082A00E7BEB/Post/p1> ; data: {\n content = nil;\n title = nil;\n user = \"0x2af2a20 <x-coredata://9D07BF41-2DC0-42C1-9DD8-6082A00E7BEB/User/p1>\";\n})") 
0

Swift 3 solución

I enfrentado la misma situación, por tanto, I m publicar una solución rápida 3 a continuación

let predicate = NSPredicate(format:"NOT (self IN %@)",[arrayofNSManagedObjects]) 
Cuestiones relacionadas