Основные данные: проблема производительности подзапроса - PullRequest
3 голосов
/ 22 апреля 2011

Я пытался узнать, есть ли способ улучшить производительность следующего предиката:

[NSPredicate predicateWithFormat:@"A=%@ and SUBQUERY($self.words,$k,$k.keyword IN %@).@count==%d", 
  <value for A>, 
  keywordList, 
  [keywordList count]];

То, что я пытаюсь сделать, это вернуть все записи A, у которых есть ключевые слова, которые ВСЕ содержатся в предоставленном массиве (keywordList). У меня есть небольшая база данных около 2000 записей. Однако ключевые слова для каждой сущности варьируются от 40 до 300 ключевых слов. Ключевые слова представлены как отношение «многие» от A к объекту под названием «Ключевые слова». Приведенный выше запрос работает, но на моем iPhone4 требуется около 7 секунд. Я хочу посмотреть, что я могу сделать, чтобы уменьшить ответ до секунды.

Спасибо, Michael

Ответы [ 2 ]

0 голосов
/ 23 апреля 2011

Это не совсем решает проблему, так как результаты, возвращаемые пересечением fetchedObjs, неверны. Это не гарантирует, что все объекты 'A' содержат все предоставленные ключевые слова. На самом деле возвращается пустой список, и весь процесс на самом деле занимает больше времени.

Что-то должно быть не так с моей моделью или предыдущим ответом. Я не получаю ожидаемых результатов. Одной альтернативой для возврата списка «A» будет возвращение списка ManagedObjectIDs из «A». [mo valueForKey: (NSString *)] возвращает объект отношения.

Примечание: я первоначально разместил этот вопрос анонимно, думая, что я вошел в систему, поэтому я не могу комментировать чей-либо ответ.

0 голосов
/ 22 апреля 2011

Я думаю, что вы подходите к проблеме задом наперед.Если у вас есть ключевые слова, вы должны найти объекты Keyword, а затем пройти их отношения A, чтобы найти связанные объекты A. Затем проверьте наложение в наборах отношений.

Итак, что-то вроде:

NSFetchRequest *fetch=//...set up fetch
[fetch setEntity:Keyword_entity];
NSPredicate *p=[NSPredicate predicateWithFormat:@"keyword IN %@",keywords];
[fetch setPredicate:p];
NSArray *fetchedObj=//... execute fetch

NSMutableSet *inCommon=[NSMutableSet setWithCapacity:[fetchedObjs count]];
for (NSManagedObject *mo in fetchedObjs){
  if ([inCommon count]==0){
    [inCommon addObjects:[mo valueForKey:@"aRelationshipName"]];
  }else{
    [inCommon intersectSet:[mo valueForKey:@"aRelationshipName"]];
  }
}

... inCommon будет содержать набор всех уникальных A объектов, которые разделяют все ключевые слова.
Update:

От автора OP:

Это не совсем решает проблему, так как результаты, возвращаемые при пересечении fetchedObjs, неверны.Это не гарантирует, что все объекты 'A' содержат все предоставленные ключевые слова.

Хорошо, давайте возьмем другую тактику.Предположим, у вас есть модель данных, которая выглядит примерно так:

A {
    keywords<<-->>Keyword.as
}

Keyword{
    keyword:string
    as<<-->>A.keywords
}

Тогда что-то вроде этого должно работать:

NSFetchRequest *keyWordFetch=//...set up fetch
[keyWordFetch setEntity:Keyword_entity];
NSPredicate *p=[NSPredicate predicateWithFormat:@"keyword IN %@",keywords];
[keyWordFetch setPredicate:p];
NSArray *fetchedKeywords=//... execute keyWordFetch


NSFetchRequest *entityAFetch=//...set up fetch
[entityAFetch setEntity:A_entity];
NSPredicate *pred=[NSPredicate predicateWithFormat:@"ALL keywords IN %@", fetchedKeywords);
[entityAFetch setPredicate:pred];
NSArray *fetchedAs=//... execute fetch
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...