在elasticsearch中存储聊天消息的最佳方式

我们目前正在我们的平台上实施即时消息系统 。 我们需要为用户提供聊天记录,并能够显示用户最近的5次对话(在Facebook上进行预览)。

事实上,我们必须考虑如何存储所有这些数据

我们正在使用Elasticsearch ,我们认为这可能是一种可靠的解决方案,用于存储聊天消息并使其高度可用于读取操作。

我们的问题是, Elasticsearch中最好的数据结构是什么,这样我们的读取操作可以很快而且不会太重。

我们想到了很多解决方案,这可能是我们想出的最佳解决方案。

我们的信息表示可能是:

{ 
   "ID" : 1,
   "sender" : "john",
   "receiver" : "doe",
   "content" : "Lorem ipsum dolor sit amet, consectetur adipiscing elit."
   "date" : "timestamp"
}

我们可以使用嵌套对象在对话中存储消息:

 {
     "ID" : 317,
     "participants" : "john, doe",
     "date" : "timestamp of the last received message",
     "messages": [
         {
            "ID": "49753",
            "sender" : "john", 
            "receiver" : "doe",
            "content" : " Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
            "date" : "timestamp" 
         },
         {
            "ID": "49754",
            "sender" : "doe", 
            "receiver" :"john",
            "content" : " Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
            "date" : "timestamp" 
         },....
               ]
}

我们希望对您的解决方案有所反馈,如果您有更好的解决方案,我们也会提供您的解决方案。

提前致谢


注意:这个建议的解决方案不仅仅是从快速读取的角度来看(如OP所要求的),而且还着眼于最小化索引开销。 嵌套文档及其父母被编写为一个块,因此在嵌套提议中添加每个额外的“消息”会导致该对话中的所有先前的消息和对话数据也被重新编制索引。

这里是我对Facebook实现消息的一般方法的猜测 (如果你使用Elasticsearch做类似的事情)

在这里输入图像描述

预览 :(在Messages导航栏下拉菜单和消息页面的左侧栏中)

使用以下内容显示最近对话的摘要:

  • 最近三位参与者中排名最近的三位参与者的综合头像。
  • 如果> 3,其他参与者的数量
  • 会话中最新消息的时间戳
  • 会话中最新消息的片段
  • 消息窗格 :(消息页面的中心列)

  • 显示对话中的所有消息
  • 消息窗格也用于消息搜索结果,显示包含搜索到的术语的所有消息。
  • 搜索框

  • Typeahead:(使用匹配的参与者名称在对话中完成)
  • 搜索:(使用消息正文中的匹配文本搜索消息)

  • 驱动预览的数据结构可能在conversation索引中(每个对话包含一个文档)。 每次将消息添加到对话时,这些文档都会更新。 (很像嵌套示例文档的父记录)。

    conversation数据源仅用于绘制预览(对会话参与者进行快速筛选,以确保您只能看到您所参与的对话)。

     {
         "ID" : 317,
         "participant_ids": [123456789, 987654321],
         "participant_names: ["John Doe", "Jane Doe"],
         "last_message_snippet" : " Lorem ipsum dolor sit amet, consectetur adipiscing elit...",
         "last_message_timestamp" : "timestamp of the last received message",
     }
    

    在这里没有嵌套B / C只需要最新的对话摘要,而不是消息。

    性能会很快,因为不需要进行评分,只需在participant_ids对[当前用户]进行过滤, last_message_timestamp进行降序排序。

    您可以使用participant_names字段上的Elasticsearch术语提示器复制预先输入功能。

    conversation文档的数量较少(与message文档相比)有助于更新此索引的索引在大范围内运行良好。

    为了进一步扩展此功能,可以使用索引每时段索引策略(时间范围取决于对话的典型半衰期,例如)。


    在特定conversation显示消息时 ,您会查询带有您的消息文档示例的message索引,但会引用conversation

     {
         "ID" : 4828274,
         "conversation_id": 317,
         "conversation_participant_ids": [123456789, 987654321],
         "sender_id": 123456789,
         "sender_name: "John Doe",
         "message" : " Lorem ipsum dolor sit amet, consectetur adipiscing elit",
         "message_timestamp" : <timestamp>,
     }
    

    性能会很快,因为不需要进行评分,只需对conversation_id进行过滤,并按message_timestamp进行降序排序。

    在跨会话搜索消息时 ,您只需将message字段编入索引。 (继Facebook之后)。

    搜索查询将是由conversation_participant_ids的[当前用户]过滤的搜索项,并按message_timestamp进行降序排序。

    为了最大限度地减少检索对话消息时搜索集群中的串扰,您需要确保利用Elasticsearch的routing参数(对索引请求进行),以便将对话的所有消息明确地共同定位在同一分片上,在索引新消息时使用conversation_id作为routing值。


    注意:对于实现一个解决方案,Elasticsearch可能会变得过于复杂,这个解决方案很大程度上可以通过具有文本搜索功能的另一个文档存储或关系数据库构建。 通过在上面的例子中规范化conversationmessage ,在Elasticsearch中不再依赖“嵌套”。

    Elasticsearch的优势包括高效的缓存过滤搜索结果,快速自动完成和快速文本搜索,但Elasticsearch的一个弱点是需要足够的内存来容纳所有索引数据。

    消息传递应用程序的性能特征决定了只有最近的消息可能以任何频率被访问或搜索,所以在某些时候,如果您的应用程序需要扩展,您应该计划一种方法来存档较旧的在“冷藏”中访问过的消息,使得它们需要较少的应用程序资源,但仍可以足够快地“解冻”以在没有过多延迟的情况下为关键字搜索提供服务。

    链接地址: http://www.djcxy.com/p/94175.html

    上一篇: Best way to store chat messages in elasticsearch

    下一篇: Decentralized Chat Communication Protocol