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

#iphone #ios #core-data

#iPhone #iOS #core-data

Вопрос:

Что у меня есть

Объект сообщения

 user  | text                          | date 
---------------------------------------------- 
user1 | This is first message user 1  | 10:50     **
user2 | This is first message user 2  | 10:50     **
user3 | This is first message user 3  | 10:50     **
user1 | This is second message user 1 | 10:00
user4 | This is first message user 4  | 10:00     **
user2 | This is second message user 2 | 10:00
user3 | This is second message user 3 | 10:00
user1 | This is third message user 1  | 9:00
...
  

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

Это

 user1|This is the first message user 1|10:50
user2|This is the first message user 2|10:50
user3|This is the first message user 3|10:50
user4|This is the first message user 4|10:00
  

Вы можете добиться этого, сначала захватив отдельных пользователей, а затем выполнив запрос на выборку для каждого пользователя с использованием предиката, но это закончится множеством «запросов» (в данном случае 5). Было бы неплохо, если бы это можно было сделать в одном запросе.

Спасибо!

Ответ №1:

Я бы добавил отношение к вашей пользовательской сущности, называемое чем-то вроде «lastMessage», которое вы всегда будете обновлять всякий раз, когда вставляете новое сообщение. Тогда проблема становится тривиальной.

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

ОТРЕДАКТИРУЙТЕ, чтобы показать объекты:

 ------------- 1  R1     * ------------
|User Entity|<----------->| Message  |
-------------             ------------
| name      |------------>| text     |
-------------    R2     1 | date     |
                          ------------
  

У вас есть две сущности — пользователь и сообщение. Настройте 2 отношения между объектами:

R1 — двунаправленный «один ко многим» (у одного пользователя много сообщений, и одно сообщение принадлежит одному пользователю)

R2 — однонаправленное взаимно однозначное сообщение ‘lastMessage’ (у одного пользователя есть одно последнее сообщение)

Обновляйте R2 всякий раз, когда вы добавляете новое сообщение.

Чтобы получить последние сообщения для всех пользователей, выполните запрос на выборку для всех пользователей, а затем просто посмотрите на отношения R2.

Используйте setPropertiesToFetch: в NSFetchRequest для заполнения отношения R2 за один переход к базе данных.

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

1. Перечитывая ваш вопрос, я не уверен, что у вас есть объект User. Если нет, создайте один и отслеживайте отдельных пользователей и их последние сообщения.

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

3. На самом деле у меня нет объекта user. Предположим, у меня есть объект user со связью с объектом Messages, сначала я получу все объекты пользовательского типа, и все отношения будут «сбиты с толку», создавая новый запрос для каждого из них. Я прав?

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

5. Прежде всего, спасибо за этот подробный ответ!! Знаете ли вы, будет ли «includeSubentities» загружать все сообщения для каждого пользователя? В конце каждый пользователь имеет отношение один ко многим с сообщениями

Ответ №2:

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

Затем выполните перечисление по набору:

 for (NSManagedObject *obj in fetchController.fetchedObjects){

}
  

Внутри этого цикла вы можете выполнить другую выборку, используя объект obj для предиката. Сортировка по дате с максимальным возвратом 1. Результирующий набор будет одним объектом, который является первым сообщением для этого пользователя.

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

1. Это то, что я делаю прямо сейчас, но у него есть проблема с растущими запросами. Для 10 разных пользователей у вас есть 11 запросов. Подумайте, что у вас есть 100 разных пользователей.