【发布时间】:2020-02-06 00:24:18
【问题描述】:
我正在尝试在 MongoDB 中找到自己的方法。这是我第一次使用这个数据库,来自 MySQL。但对于我正在制作的聊天应用程序,建议使用 MongoDB 更合适。
我有两个收藏:
对话,我在其中存储成员用户 ID(存储在 MySQL 数据库中)和加入日期。
{
"_id" : ObjectId("5e35f2c840713a43aeeeb3d9"),
"members" : [
{
"uID" : "1",
"j" : 1580580922
},
{
"uID" : "4",
"j" : 1580580922
},
{
"uID" : "5",
"j" : 1580580922
}
]
}
消息,我在其中存储发件人(用户 ID)、消息、时间戳、对话 ID(来自上面的集合)、读取和传递状态
{
"_id" : ObjectId("5e35ee5f40713a43aeeeb1c5"),
"c_ID" : ObjectId("5e35f2c840713a43aeeeb3d9"),
"fromID" : "1",
"msg" : "What's up?",
"t" : 1580591922,
"d" : {
"4" : 1580592039
},
"r" : {
"4" : 1580592339
}
}
我现在要做的是查询特定用户的对话,比如 userID 1,以及该对话中发送的最后一条消息。
我想出了以下几点:
db.getCollection('conversations').aggregate(
[{
$match: {
"members.uID": "1"
}
},
{
$lookup: {
as: 'lastMessage',
foreignField: 'c_ID',
from: 'messages',
localField: '_id',
}
},
])
但这里的问题是它列出了所有消息,而不仅仅是最后一条。所以我想将其限制为 1,或者如果有其他方法..请告诉我。
感谢任何帮助!
【问题讨论】:
-
如果您不依赖于这些特定模式,我建议将 messages 作为数组存储在 conversation 中。这应该会大大简化您想要执行的任何聚合查询,以在对话中查找特定消息(无论是第一条消息、最新消息、来自某个用户的所有消息等)。这也可能更适合您的聊天应用程序如何使用对话和消息。从本质上讲,这消除了在对话中查找消息所需的“加入”。
-
我确实考虑过这一点,但是每次添加消息时我都需要执行更新。这不是很高效,是吗?
-
插入可能比更新快,但如果您通过 _id 更新对话并且只添加新消息,则可能不会快很多。我认为将消息包含在对话中的好处超过写入性能稍慢的好处:您的数据结构更自然,在概念上更容易使用,并且读取性能得到改善,因为现在您不再需要两次调用应用程序加载对话的数据库(1 获取对话,然后 1 获取对话中的所有消息)。
-
下面的解决方案会不会不好?另外,如果消息很多,持有所有ID可能会达到16mb的限制,不是吗?
-
我看到的下面的解决方案没有任何问题(尽管我已经有一段时间没有做很多聚合了)。您可能会遇到包含大量消息的文档大小限制,所以如果这是一个现实的问题,我会考虑保留一个名为 oldMessages 的单独集合:此集合中的每个对象都包含一个消息数组,并且可以选择oldMessages 中另一个对象的 _id 用于更旧的消息。您的 conversation 条目可能有也可能没有“oldMessages”字段,如果存在的话,它是已经存在的消息之后的下一个最旧消息集的 _id。
标签: mongodb mongodb-query