Базовые данные - Получить объекты, фильтрующие данные, используя точные элементы массива

У меня есть 3 лица: object, object_tag а также tagи мне нужно получить только объекты, соответствующие массиву тегов по его идентификатору, но не просто тегу, а точно совпадающему со всеми тегами в массиве. Если массив имеет 3 тега, вернуть все объекты, которые имеют эти 3 тега, и не больше и не меньше.

Сущности похожи на:

object
{
    id
    name
    -----
    tags <--->> object_tags
}

object_tag
{
    id
    id_object
    id_tag
    -----
    object <---> tags
    tag <---> objects
}

tag
{
    id
    name
    -----
    objects <--->> object_tags
}

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

РЕДАКТИРОВАТЬ 1:

Извините, я забыл уточнить кое-что об отношениях. Сущности object а также tag указывает на промежуточный объект object_tag, который содержит пары объект-тег.

1 ответ

Решение

Следующий предикат для объекта объекта должен работать:

NSArray *tagIds = @[ @1, @4, @7 ]; // Your set of tag ids
[NSPredicate predicateWithFormat:@"(object_tags.@count == %d) AND (SUBQUERY(object_tags, $x, $x.tag.id IN %@).@count == %d)",
                      tagIds.count, tagIds, tagIds.count];

где object_tags является отношением ко многим из объекта в *object_tag*, и tag это отношение "один к одному" от * object_tag * к тегу.

Если вы упростите вашу объектную модель до отношения многих ко многим между object а также tag (как предложил Дэвид Раветти в комментарии), тогда предикат будет выглядеть так:

[NSPredicate predicateWithFormat:@"(tags.@count == %d) AND (SUBQUERY(tags, $x, $x.id IN %@).@count == %d)",
                      tagIds.count, tagIds, tagIds.count];

Если вы хотите только проверить, что объект имеет все теги из данного массива (но может иметь больше тегов), то вы можете упростить запрос до

[NSPredicate predicateWithFormat:@"SUBQUERY(tags, $x, $x.id IN %@).@count == %d",
                      tagIds, tagIds.count];
Другие вопросы по тегам