Подзапрос CoreData с несколькими условиями, отношениями

#objective-c #core-data #subquery #nspredicate

#objective-c #основные данные #подзапрос #nspredicate

Вопрос:

первый постер, давний читатель / поисковик!

Я пытаюсь вернуть информацию из подзапроса по отношению CoreData «один ко многим». У меня есть две сущности — клиенты и сообщения. У каждого клиента может быть несколько сообщений.

То, что я пытаюсь сделать, это вернуть номер учетной записи из таблицы Customers для каждого клиента, у которого есть сообщение типа «Temp-Stop» с датой вступления в силу меньше завтрашней даты.

Я попытался использовать комбинации ANY и NONE без подзапросов, но обнаружил, что они работают не так, как я хотел. Наконец, я прибегнул к подзапросу.

Как у меня есть ниже, он возвращает количество клиентов с прошлыми временными остановками, но вместо этого мне нужен номер учетной записи этих клиентов. Чтобы было ясно, конечная цель — определить, есть ли у клиента также сообщение типа «Перезапуск» до завтрашней даты. Это означало бы, что они больше не будут остановлены и должны быть включены в список активных клиентов.

(Здесь было изображение, но я не могу его опубликовать, потому что я новый пользователь)

 NSPredicate *predTemps = [NSPredicate predicateWithFormat:@"SUBQUERY(messages, $m, $m.effective < %@ amp;amp; $m.type == 'Temp Stop').@count > 0", tomorrow];
 

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

 NSPredicate *predTemps = [NSPredicate predicateWithFormat:@"SUBQUERY(messages, $m, $m.effective < %@ amp;amp; $m.type == 'Temp Stop').account", tomorrow];
 

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

Большое вам спасибо!

Ответ №1:

Поскольку ваш запрос фильтрует только атрибуты в Message объекте, есть ли причина, по которой вы не запускаете предикат непосредственно против Message объекта вместо его «родительского»?

Похоже, основываясь на информации в вашем вопросе, вы можете запустить a NSFetchRequest для своего Message объекта, а затем, если вам нужна информация о его родителе, вы можете получить к нему доступ через обратную связь.

Это даст вам доступ к учетной записи через возвращенные Message экземпляры.

Помните, что Core Data — это граф объектов, а не база данных. Итак, вы хотите возвращать и работать с объектами (сообщениями) вместо столбцов (учетная запись). Как только вы вернете объект, вы сможете извлечь из него значение учетной записи.

Обновить

Это псевдокод, объясняющий, что я имею в виду.

 NSManagedObjectContext *moc = ...;
NSDate *effectiveDate = ...;
NSError *error = nil;
NSFetchRequest *request = nil;
NSPredicate *pred = nil;

request = [NSFetchRequest fetchRequestWithEntityName:@"Message"];
pred = [NSPredicate predicateWithFormat:@"effective < %@ amp;amp; type == 'Temp Stop'", effectiveDate];
[request setPredicate:pred];

NSArray *results = [moc executeFetchRequest:request error:amp;error];
NSAssert2(!error || results, @"Error fetching results: %@n%@", [error localizedDescription], [error userInfo]);

NSArray *customers = [results valueForKey:@"customer"];

return customers;
 

Комментарии:

1. Спасибо за ваш ответ. Извините, теперь я вижу, что в моем OP не было ясно, что имя отношения также является «сообщениями». Итак, я пытался запросить его напрямую… Отношения Я тоже мог неправильно понять ваш ответ.

2. Это не меняет моего ответа, Извлекайте Сообщения. Затем вы можете получить информацию об учетной записи из объекта сообщения. Исходя из вашего вопроса, нет никаких причин когда-либо прикасаться к объекту customer во время выборки. Как только у вас есть объект сообщения, вы можете запросить сообщение для его Клиента.

3. Насколько я понимаю, я уже извлекал объект messages непосредственно с помощью первого подзапроса. В принципе, я все еще (к сожалению) не понимаю, как вернуть всех клиентов, у которых была прошлая «Временная остановка» и будущая «Перезагрузка». Еще раз спасибо…