【问题标题】:Integrated Elasticsearch with acts_as_paranoid gem with Rails 3.2使用 Rails 3.2 将 Acts_as_paranoid gem 集成到 Elasticsearch
【发布时间】:2013-12-27 15:58:19
【问题描述】:

我正在尝试从 Elasticsearch 结果中过滤掉所有已删除的记录(使用偏执 gem https://github.com/goncalossilva/acts_as_paranoid)。

acts_as_paranoid 是软删除,这个 gem 将覆盖我们模型的destroy 方法,它在我们的模型中添加了一个列名deleted_at (datetime),如果这条记录没有被删除,则设置为零。 而在 Elasticsearch 中,我想过滤掉(所有删除的记录都不应该出现在 搜索结果),但我仍然得到它们。

这是我在 elasticsearch 中的代码:

  tire.search(load: true, page: params[:page], per_page: per_page) do
    query do
      boolean do
        must { term: {"deleted_at": nil} }
      end
      filter :range, created_at: {gte: params[:created_after]} if params[:created_after]
      filter :term, city: CITIES[params[:city]] unless CITIES[params[:city]].blank?
      sort do
        by :created_at, "desc"
      end
     end
   end

我也曾尝试将filter :missing, field: :deleted_at

但它不能正常工作。 请告诉我我的错误是什么,我该如何解决?这让我抓狂@@

【问题讨论】:

  • 字段deleted_at是否在elasticsearch中被索引?
  • 是的,我使用date 类型作为deleted_at。好吗?

标签: ruby-on-rails ruby elasticsearch


【解决方案1】:

首先要调查:

deleted_at 字段是否已编入索引?

如果是,您的过滤器解决方案应该可以工作,否则

  1. 使用 deleted_at 清理所有文档,然后每当有软删除时,您必须从 elasticsearch 清理文档

  2. 你需要在索引中添加deleted_at,然后使用这个过滤器。

如果你想进行第 1 步,你可以使用这段代码:

我看到您正在使用 tire ruby​​ 客户端连接到 elasticsearch:

获取没有设置为nil的deleted_at文档的id

类似下面的代码应该可以工作

<Modelname>.all.map {|i| i.id if !usr.deleted_at.nil?}.compact #This is just an example no tests have been run to test the performance to fetch thousands of records. 

你可以用别的东西。您只需要获取已删除_at 未设置为 nil 的文档的 id

然后使用以下代码从 elasticsearch 中删除这些文档。

id_array = [1,2,3]
query = Tire.search do |search|
        search.query { |q| q.terms :_id, id_array }
      end

index = Tire.index('<index_name>') # provide the index name as you have in your code

Tire::Configuration.client.delete "#{index.url}/_query?source=#{Tire::Utils.escape(query.to_hash[:query].to_json)}"

完成此操作后,只要有软删除,您就必须使用相同的代码。您可以只发送数组中的单个 id 而不是数字数组,或者您可以使用术语过滤器而不是术语来发送单个 id

对于单个文档:

id_no = 1
query = Tire.search do |search|
        search.query { |q| q.term :_id, id_no }
      end

index = Tire.index('<index_name>') # provide the index name as you have in your code

Tire::Configuration.client.delete "#{index.url}/_query?source=#{Tire::Utils.escape(query.to_hash[:query].to_json)}"

如果您想执行第 2 步,请将 deleted_at 添加到您的 to_indexed_json 中,然后重新索引您的数据,然后使用过滤器。

【讨论】:

  • 谢谢你的回答,我试过了。但这对我来说似乎没用。我试过@nguyentrinhhongngoc 的答案,它有效,但我不明白为什么。你能解释一下吗?
  • 我的第一条语句deleted_at 字段是否被索引?如果是,则您的过滤器解决方案应该可以工作,否则 表示如果未编入索引,您需要选择此选项。正如您所说,它已添加到索引中,上述解决方案并不适用。
【解决方案2】:

你可以先删除索引再重新创建,可能你的数据在使用软删除之前受到了索引的影响。

第 1 步:删除索引

bundle exec rake environment tire:index:drop force=true INDICES=<index_name>

第 2 步:再次创建索引

bundle exec rake environment tire:import:all force=true

使用http://localhost:9200/_aliases 来检查&lt;index_name&gt;(INDICES 的值)

【讨论】:

  • 我不明白,我的索引在我开始使用软删除 gem 之前就已经存在了。但是这里的问题是什么?能给我解释一下吗?
  • 现在我明白了,您在创建索引后添加了 gem。但是该索引没有关于deleted_at 的映射详细信息。由于 deleted_at 是一个新字段,您可以尝试只使用 import all 选项而不使用 force 选项。即使这样也应该奏效。随着新字段动态映射到索引中。因此,执行重新索引将使用新的映射设置创建索引。新映射将具有 deleted_at。因此,过滤器可以正常工作。
猜你喜欢
  • 2014-06-20
  • 2016-02-25
  • 2013-11-11
  • 1970-01-01
  • 2015-02-19
  • 2016-09-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多