2010-11-26 4 views
3

Мое приложение имеет интеллектуальную папку, такую ​​как функциональность: предикат настраивается с помощью NSPredicateEditor и используется для заполнения папки запросом на выборку.Исходные данные на основе свойств упорядоченных связей

Объект, используемый в поиске, имеет отношение ко многим. Связь упорядочена в том смысле, что индекс хранится в целевом объекте для целей сортировки.

Моя проблема заключается в том, что я хотел бы построить правило, основанное на последних значениях в упорядоченном соотношении, но я не могу понять, как построить предикат для этого, потому что отношения не являются массивом. Основные данные фактически не знают о заказе.

У меня есть свойство readonly в классе, которое возвращает упорядоченные элементы, но это не похоже на запрос на выборку, потому что свойство недоступно в хранилище основных данных.

Единственным вариантом, о котором я могу думать, является де-нормализация и сохранение последних элементов в отношениях, упорядоченных в отдельном свойстве. Это единственное решение?

ответ

1

Я не думаю, что есть способ ограничить n приводит к предикату, только на уровне запроса выборки.

Помимо ссылки на последние n элементов в отношениях, как вы упомянули, вы можете попробовать логический атрибут «lastN» и включить или выключить их при выполнении заказа списка (например, во время сортировки пользователя или перетаскивание перетаскиванием).

В качестве альтернативы, вы можете создать отдельный запрос выборки для каждого искали вещь, которая сортирует ваш ключ сортировки, упорядоченный по убыванию, и ограничен (через -setFetchLimit:) к п результатов.

Отслеживание этого как отношения или атрибута несколько «беспорядочно», в то время как предел выборки является более дорогостоящим (из-за многократных круговых поездок). Если ваше переупорядочение выполняется одноразовыми действиями пользователя, возможно, лучше использовать подход зависимости или атрибута, поскольку работа амортизируется, а не выполняется все сразу в ряде наборов. Я сам не нашел лучшего пути и буду внимательно следить за этим. :-)

+0

Я надеялся, что смогу сделать это с помощью одной исходной выборки, но я начинаю думать, что это невозможно. Я чувствую, что использование дополнительных свойств - денормализация - это, вероятно, лучший способ пойти, с точки зрения производительности. – 2010-11-26 21:34:46

+0

Разумеется, метод поиска с одной выборкой на предмет объекта является ужасно расточительным и необоснованным для большого списка объектов поиска, но для небольших списков это может быть разумным ударом. Я лично использовал подход «lastN».Я думаю (но не цитирую) отношения автоматически означают многократные поездки с Core Data. – 2010-11-26 21:44:47

2

Ну, если я правильно понял проблему, я бы сделал это так. Допустим, у вас есть две сущности, у TopEntity есть свойство имени (NSString *) и отношение to-many к MyEntity, у которого есть свойство данных (NSString *) и свойство NSInteger.

Допустим, вы хотите объекты TopEntity, которые соответствуют заданной строке, и чьи MyEntity заказы удовлетворяют определенному условию, то вы можете сделать это с двумя предикатами и NSFetchRequest как так ....

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);   
} 

Итак, вы можете просто обернуть результаты вашего запроса на выбор другим предикатом и использовать ключевое слово ANY.

Я понятия не имею, насколько это эффективно, но это работает для этого случая. Запуск выше будет выводить «Это ваше имя», то есть он соответствует первому TopEntity.

Смежные вопросы