Выполнение поиска по нескольким объектам с использованием NSPredicate

Я столкнулся с проблемой, когда переносил свой код из базы данных SQLite в Core Data.

Данные, которые я использую, поступают из существующей базы данных, и поэтому все отношения определены с использованием идентификатора каждой из таблиц (или сущностей теперь, когда я использую Core Data). Моя проблема в том, что я хочу сделать запрос к одной таблице, а затем использовать этот результат для распространения данных, чтобы получить все другие данные, которые мне нужны.

Исходная база данных выглядит так:

CREATE TABLE TecAccessPoints (MAC varchar NOT NULL PRIMARY KEY UNIQUE,ZoneID integer NOT NULL,Floor integer);
CREATE TABLE Zones (ID integer NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,ZoneName varchar NOT NULL,BuildingID integer,ZoneDescription varchar);
CREATE TABLE Buildings (ID integer NOT NULL PRIMARY KEY AUTOINCREMENT,BuildingName varchar NOT NULL,CampusID integer NOT NULL,BuildingDescription varchar,Long float,Lat float);
CREATE TABLE Campuses (ID integer NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,CampusName varchar NOT NULL,CampusDescription text, Latitude float, Longitude float);

Мой исходный SQL-запрос:

SELECT DISTINCT Zones.ID, Zones.ZoneName, Buildings.ID, Buildings.BuildingName, Campuses.ID, Campuses.CampusName, Rooms.ID, Rooms.NameNumber, Rooms.Floor 
FROM Zones, TecAccessPoints, Buildings, Campuses, Rooms 
WHERE Campuses.ID = Buildings.CampusID 
   AND Buildings.ID = Zones.BuildingID 
   AND Zones.ID = Rooms.ZoneID 
   AND Zones.ID = TecAccessPoints.ZoneID 
   AND TecAccessPoints.MAC = '%@';

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

TecAccessPoints.MAC == '%@'

Затем выполните еще один поиск данных, используя возвращенные данные, например:

Zones.ID == TecAccessPoints.ZoneID

И так до тех пор, пока я не получу все нужные мне результаты?

Спасибо

Джеймс


person James    schedule 31.07.2009    source источник


Ответы (1)


Вы не можете реплицировать свой запрос как предикат Core Data, потому что вы можете получить только одну сущность за раз. Однако это может быть тот случай, когда представление о вещах как о графе объектов, а не о таблицах базы данных, может быть гораздо более плодотворным. Если у вас есть отношения

TecAccessPoints <*-> Zones <*-> Buildings <-> etc.
                           <-*> Rooms

Вы можете легко запросить TecAccessPoints, как показано выше, а затем следовать отношениям в коде, например.

TecAccessPoint *tap;
// fetch tap

Campus *campus = tap.zone.building.campus;
NSSet *rooms = tap.zone.rooms;

предполагая, что отношения названы zone, building, rooms и т. д., и у вас есть соответствующие категории NSManagedObject для определения связанных @properties, чтобы компилятор не жаловался.

Конечно, под Core Data выполняется последовательность SQL-запросов, каждый из которых представляет собой JOIN для нескольких таблиц. Core Data неплохо справляется с тем, чтобы свести это к минимуму, но если вы фанат БД, это может вас беспокоить. Если это так, вам придется придерживаться необработанного SQLite. Переход к Core Data подразумевает, что вы готовы думать о вещах на уровне графа объектов и по большей части игнорировать детали реализации.

person Barry Wark    schedule 31.07.2009
comment
Это то, чего я боялся - создание отношений между сущностями (которые требуют, чтобы они были связаны с объектом), когда текущие отношения отображаются с использованием первичных ключей в таблице - я очень хочу использовать Core Data, потому что это < i>должен сделать мой код более понятным для всех, кто присоединится к разработке в будущем, но мне нравится возможность выполнять соединения таблиц... Думаю, я столкнусь с барьером либо при импорте, сделав все отношения или по запросу, когда мне приходится вызывать каждую сущность отдельно... - person James; 01.08.2009
comment
Как вы говорите, при переводе между схемами базы данных должны быть некоторые проблемы, независимо от того, используете ли вы Core Data или нет (очевидно, что системы баз данных высокого класса или ORM могут помочь смягчить эту боль, но кто-то должен был терпеть боль, чтобы кодировать их. ..). В этом случае выполнение JOIN при импорте — правильный путь. Прежде всего, вы можете взять время кодирования (и снижение производительности во время выполнения) один раз во время импорта, а не при каждом запросе. Во-вторых, вы сможете использовать фреймворк Core Data в полной мере. - person Barry Wark; 03.08.2009
comment
Спасибо за вашу помощь с этим Барри, я решил придерживаться текущей реализации SQLite - отчасти потому, что я никого не исключаю из 2.x, а отчасти потому, что мой код импорта начал немного раздуваться. Еще одна вещь, которую я заметил, исследуя это, заключается в том, что для каждой сущности, которую я извлекаю из постоянного хранилища, основные данные помещают ее и ВСЕ ее отношения в память, где, как и в случае с SQL-запросом, я могу выбрать, какие части каких таблиц я хочу загрузить. Я сохранил основную ветку данных, чтобы вернуться к ней в будущем. Еще раз спасибо. - person James; 04.08.2009
comment
Как и любой другой, Core Data — это всего лишь инструмент. Если текущая реализация работает для вас, это здорово! Небольшое примечание: когда вы получаете экземпляр из постоянного хранилища, вы можете получить его как ошибку. Когда срабатывает эта ошибка, загружаются только атрибуты — связи по-прежнему являются ошибкой, которая не срабатывает, пока вы не пройдете эту связь. В запросе на выборку вы можете указать, хотите ли вы выполнить предварительную ошибку (т. е. загрузить) цели особых отношений из целевого объекта выборки. Вам никогда не нужно загружать все отношения, если вы этого не хотите. - person Barry Wark; 05.08.2009