Неожиданный результат составной выборки CoreData с диапазоном дат - PullRequest
1 голос
/ 05 августа 2020

У меня есть простая модель данных с посетителями (fName и lName) и посещениями (дата, комментарий) в 1-м отношении. Я пытаюсь получить всех посетителей за определенный день. Чтобы добиться этого, мне нужно создать предикат для поиска всех сущностей, имеющих посещения между началом этого дня и его концом. Я пробовал:

...
let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "visitor")
let filter = "ANY visits.date >= %@ AND ANY visits.date < %@"  // visits is the visitors relation to visits
let startTime = calendar.startOfDay(for: thisDay) as NSDate
let endTime = calendar.date(bySettingHour: 23, minute: 59, second: 59, of: thisDay)! as NSDate
fetchRequest.predicate = NSPredicate(format: filter, startTime, endTime)

Результатом являются все посетители с датами посещения на этот день и после него. Следовательно, вторая часть составного предиката не действует! Я также попытался объединить два условия с NSCompoundPredicate, но результат тот же. Я экспериментировал с другими типами данных с одним и тем же составным предикатом, и все они работали хорошо. Поэтому, несмотря на обширные поиски в Inte rnet, я не знаю, как решить этот простой запрос с помощью предикатов.

Любые предложения приветствуются!

1 Ответ

2 голосов
/ 05 августа 2020

Ваш предикат выбирает всех посетителей, которые связаны с (хотя бы одним) посещением с visits.date >= startDate и (по крайней мере с одним) посещением с visits.date < endDate. Проблема в том, что эти два связанных объекта не обязательно должны быть одинаковыми, чтобы предикат возвращал true.

Вам нужен «подзапрос»: из (связанной) NSExpression документации :

Этот метод создает подвыражение, оценка которого возвращает подмножество коллекции объектов. Он позволяет создавать сложные запросы по отношениям, такие как поиск нескольких коррелированных значений в целевом объекте отношения.

...

Формат строки для выражения подзапроса:

SUBQUERY(collection_expression, variable_expression, predicate);

где выражение - это выражение предиката, которое оценивается как коллекция, variableExpression - это выражение, которое будет использоваться для содержания каждого отдельного элемента коллекции, а предикат - это предикат, используемый для определения принадлежности элемента к коллекция результатов.

В вашем случае это должно быть (непроверено):

NSPredicate(format: "SUBQUERY(visits, $v, $v.date >= %@ and $v.date < $@).@count > 0",
            startTime, endTime)

Это выбирает всех посетителей, которые связаны хотя бы с одним посещением, дата которого попадает в указанную диапазон.

...