С чем едят SUBQUERY

Давно хотел разобраться, что же такое за зверь такой SUBQUERY в предикатах и собственно в применении к CoreData, а тут увидел вопрос на сайте, и решил сам посмотреть. Пару раз видел это на сайтах, но обычно другие разработчики сразу начинают махать руками и не рекомендуют использовать эти выражения. Сразу поясню про что идет речь. Выражения типа:

(SUBQUERY(residents, $x, $x.firstname == «Jane» && $x.lastname == «Doe»).@count != 0) (это как раз правильного subquery)

Оказывается все просто.

SUBQUERY(collection, variableName, predicateFormat)

Данная конструкция служит простой цели: когда мы хотим отфильтровать какой то набор данных (collection) по каким-то условиям. В данном примере мы ищем внутри коллекции residents людей с именем Jane Doe. Здесь надо остановиться и сказать, почему профессионалы против использования слово SUBQUERY. Просто потому, что его не надо использовать при каждом удобном случае. Core Data это не база данных и не средство управления базой данных. Это фреймворк со своей идеологией, и документацией ))) которую надо читать и изучать. Слово subquery не означает, что вы его должны постоянно использовать для запросов к Core Data — ведь для этого есть масса других более легких и быстрых методов.

Этот синтакис лучше всего использовать в одном и только в одном случае. Когда вам надо отфильтровать какую-то коллекцию объектов, каждый из которых связан с другой коллекцией объектов, по признакам которых (не менее двух) мы и хотим фильтровать. Вот тут коллега раскрывает все тайны волшебного слова SUBQUERY. Он пишет, что пусть у нас есть много объектов Project и к каждому из них есть куча объектов ToDo. И мы хотим найти все проекты, которые были выполнены Joey. Самое простое, что нам может прийти в голову это написать:

ANY todos.completionDate != nil AND ANY todos.user == Joey

, но тут нас подстерегает беда. Нам будут возвращены все записи joey и все записи с законченными todo. Мы не получим то, что нам надо. Тут нам на помощь и приходит SUBQUERY. Следующая запись уже вернет нам только нужные строчки.

SUBQUERY(todos, $todo, $todo.completionDate != nil AND $todo.user = ‘Joey’).@count > 0

Два других «нерабочих» варианта описаны в документации Apple.

For example, suppose you have an Apartment entity that has a to-many relationship to a Resident entity, and that you want to create a query for all apartments inhabited by a resident whose first name is «Jane» and whose last name is «Doe». Using only API available for Mac OS X v 10.4, you could try the predicate:

resident.firstname == "Jane" && resident.lastname == "Doe"

but this will always return false since resident.firstname and resident.lastname both return collections. You could also try:

resident.firstname CONTAINS "Jane" && resident.lastname CONTAINS "Doe"

but this is also flawed—it returns true if there are two residents, one of whom is John Doe and one of whom is Jane Smith. The only way to find the desired apartments is to do two passes: one through residents to find «Jane Doe», and one through apartments to find the ones where our Jane Does reside.

Subquery expressions provide a way to encapsulate this type of qualification into a single query.

Реклама

Добавить комментарий

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

Логотип WordPress.com

Для комментария используется ваша учётная запись WordPress.com. Выход / Изменить )

Фотография Twitter

Для комментария используется ваша учётная запись Twitter. Выход / Изменить )

Фотография Facebook

Для комментария используется ваша учётная запись Facebook. Выход / Изменить )

Google+ photo

Для комментария используется ваша учётная запись Google+. Выход / Изменить )

Connecting to %s