elasticsearch - 在 Elixir Phoenix 中保存/更新后在 Elasticsearch 中创建文档
问题描述
我试图找出在 SQL 数据库中创建新行之后将文档插入/更新到 elasticsearch(或任何 nosql 数据库)的最佳流程,以及将逻辑放在 Elixir Phoenix 中的位置。
想象一下我的 SQL 表是posts
has_many comments
,并且我的 elasticsearch 结构有一个posts
索引,其中comments
是一个嵌套文档,所以我可以同时搜索/检索帖子和评论内容。这意味着如果用户创建或更新他们的评论消息,post
弹性搜索中的相关文档应该更新。
最好的方法是什么?
解决方案
确切的实现可能取决于几件事:操作有多快,用户是否需要知道结果?
如果两个操作都相当快(即用户可以等待),那么您可以使用一个简单的with
语句来确保两个操作都成功完成,例如
with {:ok, _result1} <- update_postgres(data),
{:ok, _result2} <- update_elasticsearch(data) do
{:ok, "Everything updated!"}
end
如果您需要围绕将 2 个操作“绑定”在一起的更多形式,那么Ecto 事务就可以完成这项工作。文档通常假设操作都是数据库操作或者它们使用相同的操作Repo
,但是您可以在事务中执行任意任务,例如更新 Elasticache:
def two_things(data) do
My.Repo.transaction fn ->
with {:ok, _result1} <- update_postgres(data),
{:ok, _result2} <- update_elasticache(data)
do
{:ok, "Everything updated!"}
else
{:error, e} ->
My.Repo.rollback(e)
{:error, "Something failed!"}
end
end
end
只有当您需要在失败时执行回滚时,使用事务才真正有意义。
此处的另一个选项假定操作可能足够慢,以至于您不希望让用户等待它们完成。通常,至关重要的“主要”操作是更新数据库。有时其他相关的更新(例如在缓存层中)最好留给异步的副作用。例如:
result = update_postgres(data)
Task.async(fn -> update_elasticache(data) end)
result
或者只有在数据库操作成功时才触发副作用:
case update_postgres(data) do
{:ok, result} ->
Task.async(fn -> update_elasticache(data) end)
{:ok, result}
{:error, error} -> {:error, error}
end
或者更简洁的语法:
with {:ok, result} <- update_postgres(data) do
Task.async(fn -> update_elasticache(data) end)
{:ok, result}
end
有许多语法/助手可以完成此操作,但其想法是任何辅助操作都是非阻塞的,并且可以在将结果返回给用户后完成。
推荐阅读
- python - 使用新数据测试文本分类 ML 模型失败
- javascript - 将对象数组转换为嵌套对象数组js
- angular - Angular Link 未通向组件
- r - 为什么我的新 var 名称显示为“... <- NULL”
- selenium - 使用 selenium webdriver 单击隐藏元素
- java - Spring Boot - SimpMessagingTemplate 没有在具有 Spring Boot 安全性的 Spring Boot WebSocket 中向客户端发送消息
- java - 媒体编解码器完全耗尽输出缓冲区
- python-3.x - 如何修复 Microsoft 扬声器识别 API 中未启动的响应
- multithreading - 使用 newrelic 和 kotlin 协程跟踪事务
- mysql - 如何将 XML 上传到 MySQL 以响应 axios 和 nodejs