Reputation: 5093
What I have
Message Entity
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
...
With that data I want to grab the first message of each distinct user using CoreData in a single fetch request.
That is
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
You can achieve that by grabbing first the distinct users, and then, perform a fetch request for each user using a predicate, but it will end with a lot of "queries" (5 in this case). It would be nice if it can be done in a single request.
Thanks!
Upvotes: 1
Views: 92
Reputation: 6372
There's an easier way. Do a fetch request of the user fields. This will produce a set containing each distinct user.
Next, enumerate through the set:
for (NSManagedObject *obj in fetchController.fetchedObjects){
}
Inside this loop, you can do another fetch using the obj object for the predicate. Sort by date wiht a maximum return of 1. The resulting set will be one object which is the first message for that user.
Upvotes: 0
Reputation: 13675
I would add a relationship to your user entity called something like 'lastMessage' which you will always keep up-to-date whenever you insert a new message. Then the problem becomes trivial.
In my experience it's easier to de-normalize your schema slightly to improve performance rather than trying to create really complex queries.
EDIT to show entities:
------------- 1 R1 * ------------
|User Entity|<----------->| Message |
------------- ------------
| name |------------>| text |
------------- R2 1 | date |
------------
You have two entities - User and Message. Set up 2 relationships between the entities:
R1 - 'messages' bidirectional one-to-many (one user has many messages and one message belongs to one user)
R2 - 'lastMessage' unidirectional one-to-one (one user has one last message)
Keep R2 up-to-date whenever you add a new message.
To get last messages for all users perform a fetch request for all users and then just look at the R2 relationship.
Use setPropertiesToFetch: on the NSFetchRequest to populate the R2 relationship in a single trip to the database.
Upvotes: 2