我有论坛。每个主题都有像viewCount这样的字段 - 论坛用户查看主题的次数。
我希望所有主题领域都来自ES(id,date,title,content和viewCount)。但是,在每个主题视图ES之后的这种情况必须再次重新索引整个文档 - 我在堆栈上询问了有关部分更新的问题 - Partial update on field that is not indexed。重要的是要注意 - viewCount字段没有编入索引,它只是存储在ES中。
问题在于有两个术语 - 部分更新和部分索引。 ES中有部分更新 - 您只能更改几个字段。 Bu没有部分重新索引 - 这意味着如果你甚至只更改一个字段,ES将重新索引整个文档。这意味着如果主题被查看1000次,ES将索引1000次。如果我有很多用户,许多文档将被反复索引。这是第一个策略。
我认为第二个策略是从索引中获取一些主题字段,从数据库中获取一些主题。在这种情况下,我从DB获取viewAcount。但是,我可以将所有字段存储在数据库中,并仅使用索引作为INDEX - 来获取当前主题的ID。
解决此类问题的最佳方法是什么?
答案 0 :(得分:10)
关于文档的部分更新,重要的是要认识到,虽然API允许您在幕后执行部分更新,但它会通过检索文档,更改文档并重新编制索引来执行完整更新。以下内容来自Elasticsearch网站:
在更新整个文档时,我们说更新文档的方法是检索文档,更改它,然后重新索引整个文档。这是真的。但是,使用更新API,我们可以进行部分更新,例如在单个请求中递增计数器。
我们还说文件是不可变的:它们不能改变,只能被替换。更新API必须遵守相同的规则。在外部,似乎我们正在部分更新文档。但是,在内部,更新API只管理我们已经描述的相同的retrieve-change-reindex进程。不同之处在于此过程在分片中发生,从而避免了多个请求的网络开销。通过缩短检索和重新索引步骤之间的时间,我们还可以降低与其他流程发生冲突的可能性。
要将全文数据存储在Elasticsearch中并且具有经常更改的字段而不重新索引整个文档,您需要将这些项存储在其他位置。这可以是另一个Elasticsearch索引或另一个系统中的元数据/计数器存储。
对于常见用例,您可以对两者运行相同的查询并合并结果。这些很可能是简单的过滤器,并且对不改变的字段进行排序,例如:主题,创作时间,作者等。
对于不匹配的搜索,例如全文查询,您可以(a)不显示该数据,或者(b)使用最终一致的方法,您可以使用更新的计数定期更新Elasticsearch主题存储。许多不具有高一致性要求的系统可以使用最终一致性方法,包括Stack Overflow,Netflix等。例如,在某些站点上,您将在一个页面/窗口小部件上获得一个计数,而在另一个页面上获得另一个计数/小部件由于最终的一致设计。
答案 1 :(得分:6)
对我来说,似乎在使用ES的情况下,您应该只更新索引中的所有数据并查询它。如果您要分割文本(据我所知,您在ES中存储用于文本搜索的主题)和数据存储之间的“数字”数据,您将体验到比在ES中重新索引文档的情况更大的性能损失。
ES唯一可以处理索引中的文档 - 索引和删除。因此,有两种方法可以加速重建索引
加速“有效负载” - 减少删除文档和删除文档所需的时间
再次索引它。这可以通过移动ES index to memory来实现,以利用 Lucene 的RamIndexStore
减少网络开销 - 使用scripts
答案 2 :(得分:0)
我想最好的方法是重新考虑你的索引设计。创建另一个索引可能是有意义的,该索引具有较少的字段数,因此索引/更新成本较少,从而将ID映射到它们各自的视图计数。然后,您的客户端可以发出两个查询以获取所有必需的信息。