Фильтр NSPredicate для отношений «многие ко многим ко многим» - PullRequest
3 голосов
/ 29 сентября 2011

Я все еще довольно новичок в использовании NSPredicate, но у меня есть несколько сложная проблема, и я не совсем уверен, что лучший способ найти решение.

Я пытаюсь создать фильтр для сущности с именем Instrument, который можно использовать со многими процедурами. Процедуры, в свою очередь, связаны с одним или несколькими заболеваниями. Заболевания связаны со многими процедурами, и инструменты могут использоваться более чем в одной процедуре. Другими словами, у меня есть следующие отношения «многие ко многим ко многим»:

Instruments <-> Procedures <-> Diseases

Что я хотел бы сделать, так это отфильтровать инструменты, используя Disease.title. В простом и волшебном мире это было бы так просто, как

//where predicate is used on the Instruments array
[NSPredicate predicateWithFormat:@"(procedures.diseases.title == %@)", diseaseTitleString];

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

Я ничего не получаю.

Я также пытался использовать (ALL procedures.diseases.title == %@), но это тоже не работает.

Я видел кое-что о под-предикатах, но ничто из того, что действительно показалось мне чем-то, что работает или имеет большой смысл для меня.

В основном я хочу получить список:

NSArray *instruments = [[NSArray alloc] init];
for (Disease *disease in Diseases) {
  if ([disease.title isEqualToString:titleString]) {
    for (Procedure *procedure in disease.procedures) {
      for (Instrument *instrument in procedure.instruments) {
        if (![instruments containsObject:instrument]) {
          [instruments addObject:instrument];
        }
      }
    }
  }
}

Прямо сейчас я использую этот метод для получения массива, который я могу фильтровать на основе других предикатов, и он работает нормально, но это уродливо, и я чувствую, что есть лучший, более чистый способ фильтрации этого. Может ли кто-нибудь помочь рассказать мне о более тонком использовании дизайна NSPredicate?

1 Ответ

2 голосов
/ 29 сентября 2011

В предикате, который у вас есть выше, замените двойные равные одинаковыми.Также добавьте пункт «ЛЮБОЙ».Наконец, удалите скобки.Таким образом, у вас будет:

[NSPredicate predicateWithFormat:@"ANY procedures.diseases.title = %@", diseaseTitleString];

В общем, я считаю, что хороший способ обработки сложных предикатов состоит в том, чтобы создать их с использованием поддиплат.

Итак, вы начинаете с:

        NSMutableArray *subpredicates = [NSMutableArray array];

Затем шаг за шагом вы добавляете свои субпредикаты:

[subpredicates addObject:
    [NSPredicate predicateWithFormat:@"ANY procedures.diseases.title = %@",
         diseaseTitleString]]

[subpredicates addObject:anotherPredicate etc];

Наконец, создайте свой предикат "и" или "или", например:

 NSPredicate *andPredicate = [NSCompoundPredicate andPredicateWithSubpredicates:subpredicates];
...