SearchKick:search_index.refresh如何与异步回调一起使用?

发布于 2025-01-24 02:01:52 字数 1202 浏览 2 评论 0原文

在典型的导轨控制器中,我们创建POST模型,然后重定向到Posts_path索引操作使用搜索kick列出帖子。

# In the model
class Post < ApplicationRecord
  searchkick callbacks: :async
end

# In the controller
def index
  @posts = Post.search("*")
end

def create
  Post.create!(post_params)
  redirect_to posts_path
end

但是,由于Elasticsearch最终是一致的,因此有时重定向发生在搜索Kearchkick/Elasticsearch索引该记录之前。

搜索Kick的文档指出一个人可以使用post.search_index.refresh等待索引赶上新记录。因此,人们可以写:

def create
  Post.create!(post_params)
  Post.search_index.refresh
  redirect_to posts_path
end

但是,有时我们仍然重定向到/posts而没有看到新创建的记录;我认为这是因为我们正在使用回调:: async,所以搜索Kickick(和elasticsearch :: api :: Indices :: Indices :: Indicesclient在幕后使用)无法了解排队搜索Kecrekick :: Reindexv2Job

如果是这样,那么如何解决此用例,即:#CREATE#destroy操作已创建/销毁了搜索Kinkick-indexed记录,重定向在#index操作中,请确保使用异步回调时的记录已经在索引上?

In a typical Rails controller, we create a Post model and then redirect to posts_path. The index action uses Searchkick to list Posts.

# In the model
class Post < ApplicationRecord
  searchkick callbacks: :async
end

# In the controller
def index
  @posts = Post.search("*")
end

def create
  Post.create!(post_params)
  redirect_to posts_path
end

However, since Elasticsearch is eventually consistent, sometimes the redirect occur before Searchkick/Elasticsearch indexed that record.

Searchkick's docs state that one could use Post.search_index.refresh to wait for the index to catch up with the new record. So one could write:

def create
  Post.create!(post_params)
  Post.search_index.refresh
  redirect_to posts_path
end

However, sometimes we still redirect to /posts without seeing the newly created record; I think that it's because we're using callbacks: :async, so Searchkick (and Elasticsearch::API::Indices::IndicesClient which is used behind the scenes) has no way to know about the queued Searchkick::ReindexV2Job.

If that's the case, how does one solve this use-case, which is: after the #create or #destroy action have created/destroyed a Searchkick-indexed record, redirect to the #index action making sure that the record is already on the index, when using async callbacks?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

怪我太投入 2025-01-31 02:01:52

elasticsearch :: api :: indices :: indicesclient在幕后使用)无法知道排队的搜索:: reidindexv2job。

您的猜测是正确的。您的背景作业可能尚未执行,因此刷新search_index无济于事。

为了解决问题,我们需要同步(在同一线程中)同步索引。幸运的是,您可以更改 Reindexing策略在运行时搜索Kackbacks。在您的情况下,我建议通过搜索Kallbacks(:inline)同步reindex :

def create
  # reindex synchonously
  Searchkick.callbacks(:inline) do
    Post.create!(post_params)
  end

  # ensure that all changes are reflected by the ES index
  Post.search_index.refresh

  redirect_to posts_path
end

Elasticsearch::API::Indices::IndicesClient which is used behind the scenes) has no way to know about the queued Searchkick::ReindexV2Job.

Your guess is correct. It's possible that your background job hasn't been executed yet, so refreshing the search_index won't help.

To fix the issue, we need to reindex synchronously (in the same thread). Luckily you can change the reindexing strategy of Searchkick callbacks in runtime. In your scenario, I recommend to reindex synchronously via Searchkick.callbacks(:inline):

def create
  # reindex synchonously
  Searchkick.callbacks(:inline) do
    Post.create!(post_params)
  end

  # ensure that all changes are reflected by the ES index
  Post.search_index.refresh

  redirect_to posts_path
end
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文