如何获取最近的关系项而不是 Android 房间中的列表
How to get the most recent relation item instead of a list in Android Room
我的结构如下:
包含一条或多条消息的对话。
Conversation 和 Message 都在各自的表中。
我创建了一个 ConversationDetailed 关系 POJO,将 Conversation 与其消息列表合并。
public class ConversationDetailed {
@Embedded
public Conversation conversation;
@Relation(
parentColumn = "id",
entityColumn = "conversation_id",
entity = Message.class
)
public List<Message> messageList;
}
到目前为止,这按预期工作,没有发现任何问题。
现在我正在尝试创建一个 ConversationSummary 关系,其中只有属于该对话的最新消息,我无法在任何地方找到如何执行此操作的示例。这就是我想要实现的目标:
public class ConversationSummary {
@Embedded
public Conversation conversation;
@Relation(
parentColumn = "id",
entityColumn = "conversation_id",
entity = Message.class
)
public Message recentMessage; // <- the most recent message of this conversation
}
我知道我可以使用 ConversationDetailed 并只从列表中选择最新的消息,但这意味着无需从数据库中查询大量消息,而我只需要最新的消息。
我怎样才能像上面的例子一样使用 Relation POJO 来实现这一点?
编辑:在尝试了另一个用户建议的初始答案后,我发现关系是单独的查询,这就是为什么使用 Relation POJO 的查询使用 Transaction 的原因,所以问题仍然没有答案。有没有办法指定关系项的顺序?
EDIT2:经过提供第一个答案的同一用户的详细解释后,我终于能够完成这项工作。这是适用于我的案例的基本原理。
MAX 与 JOIN 的组合允许我 select select 包含最新消息的对话,包括与该消息无关的所有对话。
为会话 ID 添加 GROUP BY 拆分上述逻辑以获得每个唯一会话 ID 的 MAX。
之后是将 ORDER BY 应用于消息创建日期的问题。
@Query(
"SELECT " +
"*, MAX(Message.date)" +
"FROM Conversation " +
"JOIN Message " +
"ON Conversation.id = Message.conversation_id " +
"GROUP BY Conversation.id " +
"ORDER BY Message.date DESC "
)
abstract List<ConversationSummary> getSummaryList();
尝试下一个解决方法(因为我不知道只用 Relations
做你想做的事情的直接方法):
- 编写查询以获取对话中的所有最新消息。假设您有一些字段
posted
可用于定义消息是最近的(换句话说,您应该找到最大 posted
的详细对话)。
- 使用
Room Relations
将 Conversation
实体附加到查询结果。
因此,附加 class(查询应 return 列表 Class 值):
public class RecentMessage {
@Embedded
public Message recentMessage;
@Relation(
parentColumn = "conversation_id",
entityColumn = "id"
)
public Conversation conversation;
}
并查询:
SELECT * FROM conversation_detailed as table1 JOIN (select conversation_id, max(posted) as posted from conversation_detailed) as table2 on table1.conversation_id=table2.conversation_id and table1.posted = table2.posted
@Relation 似乎从未被设计为考虑来自自定义@Query 的排序。这已在位于此处的与此问题相关的问题中得到确认:https://issuetracker.google.com/issues/128470264
第二好的选择是使用多个查询并手动构建返回的数据结构,按照链接问题中的建议。
对于我的情况,它将是两个表之间的 JOIN,按对话 ID 分组并按最新消息排在第一位。
想分享一个替代解决方案,一个我应用于我自己的相同问题的解决方案。您可以改为在对话中保存对最新消息的引用,确保正确编写,然后在您的关系中使用它。例如,您可以将“recent_message_id”添加到 Conversation,然后将其用于与“message_id”相关的特定消息。当然,这假设 Message 中有一个“message_id”。
public class ConversationSummary {
@Embedded
public Conversation conversation;
@Relation(
parentColumn = "recent_message_id",
entityColumn = "message_id",
entity = Message.class
)
public Message recentMessage;
}
我的结构如下:
包含一条或多条消息的对话。 Conversation 和 Message 都在各自的表中。 我创建了一个 ConversationDetailed 关系 POJO,将 Conversation 与其消息列表合并。
public class ConversationDetailed {
@Embedded
public Conversation conversation;
@Relation(
parentColumn = "id",
entityColumn = "conversation_id",
entity = Message.class
)
public List<Message> messageList;
}
到目前为止,这按预期工作,没有发现任何问题。 现在我正在尝试创建一个 ConversationSummary 关系,其中只有属于该对话的最新消息,我无法在任何地方找到如何执行此操作的示例。这就是我想要实现的目标:
public class ConversationSummary {
@Embedded
public Conversation conversation;
@Relation(
parentColumn = "id",
entityColumn = "conversation_id",
entity = Message.class
)
public Message recentMessage; // <- the most recent message of this conversation
}
我知道我可以使用 ConversationDetailed 并只从列表中选择最新的消息,但这意味着无需从数据库中查询大量消息,而我只需要最新的消息。
我怎样才能像上面的例子一样使用 Relation POJO 来实现这一点?
编辑:在尝试了另一个用户建议的初始答案后,我发现关系是单独的查询,这就是为什么使用 Relation POJO 的查询使用 Transaction 的原因,所以问题仍然没有答案。有没有办法指定关系项的顺序?
EDIT2:经过提供第一个答案的同一用户的详细解释后,我终于能够完成这项工作。这是适用于我的案例的基本原理。
MAX 与 JOIN 的组合允许我 select select 包含最新消息的对话,包括与该消息无关的所有对话。 为会话 ID 添加 GROUP BY 拆分上述逻辑以获得每个唯一会话 ID 的 MAX。 之后是将 ORDER BY 应用于消息创建日期的问题。
@Query(
"SELECT " +
"*, MAX(Message.date)" +
"FROM Conversation " +
"JOIN Message " +
"ON Conversation.id = Message.conversation_id " +
"GROUP BY Conversation.id " +
"ORDER BY Message.date DESC "
)
abstract List<ConversationSummary> getSummaryList();
尝试下一个解决方法(因为我不知道只用 Relations
做你想做的事情的直接方法):
- 编写查询以获取对话中的所有最新消息。假设您有一些字段
posted
可用于定义消息是最近的(换句话说,您应该找到最大posted
的详细对话)。 - 使用
Room Relations
将Conversation
实体附加到查询结果。
因此,附加 class(查询应 return 列表 Class 值):
public class RecentMessage {
@Embedded
public Message recentMessage;
@Relation(
parentColumn = "conversation_id",
entityColumn = "id"
)
public Conversation conversation;
}
并查询:
SELECT * FROM conversation_detailed as table1 JOIN (select conversation_id, max(posted) as posted from conversation_detailed) as table2 on table1.conversation_id=table2.conversation_id and table1.posted = table2.posted
@Relation 似乎从未被设计为考虑来自自定义@Query 的排序。这已在位于此处的与此问题相关的问题中得到确认:https://issuetracker.google.com/issues/128470264
第二好的选择是使用多个查询并手动构建返回的数据结构,按照链接问题中的建议。
对于我的情况,它将是两个表之间的 JOIN,按对话 ID 分组并按最新消息排在第一位。
想分享一个替代解决方案,一个我应用于我自己的相同问题的解决方案。您可以改为在对话中保存对最新消息的引用,确保正确编写,然后在您的关系中使用它。例如,您可以将“recent_message_id”添加到 Conversation,然后将其用于与“message_id”相关的特定消息。当然,这假设 Message 中有一个“message_id”。
public class ConversationSummary {
@Embedded
public Conversation conversation;
@Relation(
parentColumn = "recent_message_id",
entityColumn = "message_id",
entity = Message.class
)
public Message recentMessage;
}