I have the following schema in my application (simplified for ease)
@PrimaryKey(serverId)
data class Server(
val serverId: Long,
val serverDescription: String
)
@PrimaryKey(siteServerId, siteSiteId)
data class Site(
val siteServerId: Long,
val siteSiteId: Int,
val siteDescription: String
)
@PrimaryKey(groupServerId, groupGroupId)
data class Group(
val groupServerId: Long,
val groupSiteId: Int,
val groupGroupId: Int,
val groupDescription: String
)
@PrimaryKey(messageServerId, messageId)
data class Message(
val messageServerId: Long,
val messageId: String,
val messageGroupId: Int,
val messageBody: String,
val messageReadStatus: Boolean
)
I want to show in the UI a list as the following example
Server Description 1
Site 1 -> UnReadMessages 8
Group 1 -> UnReadMessages 5
Group 2 -> UnReadMessages 3
Site 2 -> UnReadMessages 5
Group 3 -> unReadMessages 1
Group 4 -> unReadMessages 4
Server Description 2
Site 1 -> UnReadMessages 4
Group 1 -> UnReadMessages 1
Group 5 -> UnReadMessages 3
The Servers are the different Accounts that i have. There is a possibility that i could be in the same (SiteID, GroupID) from 2 Servers.
In order to achieve this i have the following pojos
data class SiteItem(
@Embedded
val site: Site,
@Relation(entity = Group::class, entityColumn = "groups_site_id", parentColumn = "sites_site_id")
val groupItems: List<GroupItem>
) {
fun getSiteUnreadCount(): Int =
groupItems.sumOf {
it.getGroupUnreadCount()
}
}
data class GroupItem(
@Embedded
var group: Group,
@Relation(entity = Message::class, parentColumn = "groups_group_id", entityColumn = "messages_group_id")
var messages: List<Message>
) {
fun getGroupUnreadCount(): Int {
return messages.filter { it.isIncome == 1 && it.isRead == false }
}
}
So using the Room 2.4.2 i have the following query
@Query("""
Select * from servers
inner join sites on servers.server_id = sites.sites_server_id"""
)
fun getServerItems(): LiveData<Map<Server, List<SiteItem>>>
The expected result should have been something like that
RESULT = Map (
key: Server(serverId: 1, serverDescription: "Server 1"),
value: [
SiteItem(
site: Site(siteServerId: 1, siteSiteId: 1, siteDescr: "Site 1"),
groupItems: [
GroupItem(
Group(groupServerId: 1, groupSiteId: 1, groupGroupId: 1, groupDesc: "Group 1"), List<Message> : [...messages...],
GroupItem(
Group(groupServerId: 1, groupSiteId: 1, groupGroupId: 2, groupDesc: "Group 2"), List<Message> : [...messages...]
)],
SiteItem(
site: Site(siteServerId: 1, siteSiteId: 2, siteDescr: "Site 2"),
groupItems: [
GroupItem(
Group(groupServerId: 1, groupSiteId: 2, groupGroupId: 3, groupDesc: "Group 3"), List<Message> : [...messages...],
GroupItem(
Group(groupServerId: 1, groupSiteId: 2, groupGroupId: 4, groupDesc: "Group 4"), List<Message> : [...messages...]
)]
],
key: Server(serverId: 2, serverDescription: "Server 2"),
value: [
SiteItem(
site: Site(siteServerId: 2, siteSiteId: 1, siteDescr: "Site 1"),
groupItems: [
GroupItem(
Group(groupServerId: 2, groupSiteId: 1, groupGroupId: 1, groupDesc: "Group 1"), List<Message> : [...messages...],
GroupItem(
Group(groupServerId: 2, groupSiteId: 1, groupGroupId: 5, groupDesc: "Group 5"), List<Message> : [...messages...]
)]
]
However what i get can be shown in the following image

Does anyone knows how can i solve that?
Original Question, to which this answer applies (as the question has been drastically changed):-
How to observe LiveData of nested relation POJO android room The schema of my Database has 4 tables Server, Sites, Groups and Messages. Every Server has many Sites and every Site has many Groups.
There is a POJO called GroupItem that holds the Group and the unreadMessages of the Group.
The unReadCounter field can be found only with a join with the Messages table.
I also have a POJO that holds a Site with its GroupItems
So in my UI i want to display a list of a Server with all its SiteItems. So i thought of using Room 2.4.2 by observing the query
When i try to build the project i get the error
There is a problem with the query: [SQLITE_ERROR] SQL error or missing database (no such column: unreadCounter)
Answer Provided
I can understand the issue and why this is happening. Its because it cannot know how to fill up this field. I guess i have to do a double query or something in a transaction, but how can i do that since i want to return a LiveData of a Map to the UI? How can i solve this kind of a problem?
As you have:-
a) the @Columninfo annotation has no purpose so really you just have
val unreadCounter: Intb) there will be no such column, so it would need to be generated.SELECT *,(SELECT count(read_status) FROM messages WHERE groups_group_id = g.group_id AND read_status) AS unreadCounter FROM groups AS g WHERE group_id=:group_id.Assuming that, in addition to your description of the relationships, a Group has many messages which can be either read or unread the the following is an working example that gets the unread messages for a group and also for a site.
It uses a function rather than a query to ascertain the unread count.
First the @Entity annotated classes Server, Site, Group and Message for the 4 tables :-
Now some POJO classes :-
First GroupWithMessages :-
and second an adaptation of your SiteItem POJO :-
All of the dao functions in interface Alldao :-
an
@Databaseannotated class TheDatabase :-Finally putting it all together in an activity (designed to run just the once) which inserts various data and then uses the getServerItems function to drive a loop that reports on the data:-
Running the above results in the log :-
i.e. of the 4 messages added (to Group1, which has Site1 as it's parent which has Server1 as it's parent) 3 are unread an 1 is read.
Aditional
Replicating you original (aka demonstrating the "complexity") here's some additional code.
GroupItem and another version of of SiteItem i.e. SiteItemV2
The associated @Dao functions :-
and the activity code that uses the above:-
and the result :-