运行测试时,ElasticSearch Rails resource_already_exists_exception

时间:2018-09-28 20:58:09

标签: ruby-on-rails ruby elasticsearch minitest elasticsearch-rails

我正尝试运行其中的一项测试,即进行搜索,并试图断言在搜索结果中包含记录,但与此同时,我收到了Elasticsearch::Transport::Transport::Errors::BadRequest错误:

SearchTest#test_simple_test_returns_product:
Elasticsearch::Transport::Transport::Errors::BadRequest: [400] 

{
  "error":{
    "root_cause":[
      {
        "type":"resource_already_exists_exception",
        "reason":"index [app_application_test_products/FTt1YC6eQrCw2XwJuqjmDw] already exists",
        "index_uuid":"FTt1YC6eQrCw2XwJuqjmDw",
        "index":"app_application_test_products"
      }
    ],
    "type":"resource_already_exists_exception",
    "reason":"index [app_application_test_products/FTt1YC6eQrCw2XwJuqjmDw] already exists",
    "index_uuid":"FTt1YC6eQrCw2XwJuqjmDw",
    "index":"app_application_test_products"
  },
  "status":400
}

当我在开发中执行搜索时,它可以按预期工作,但是在测试中抛出了这样的错误,在测试中,我添加了导入和索引刷新,除此之外:

class SearchTest < ActiveSupport::TestCase
  setup do
    Product.import force: true
    Product.__elasticsearch__.refresh_index!
  end

  test "simple test returns product" do
    product = products(:one)
    I18n.locale = product.market.lang
    search = Search.new(
      category: product.category.custom_slug,
      page: 1,
      market_id: product.market_id,
      status: "active",
      seed: Date.today.to_time.to_i
    )
    assert_includes search.results.records, products(:one)
    assert_includes search.results.records, products(:two)
    assert_not_includes search.results.records, products(:three)
  end
end

我们希望能提供任何帮助,以帮助您改进代码。

我正在使用:

# Gemfile
gem 'minitest', '5.10.1'

# Gemfile.lock
elasticsearch (6.1.0)
elasticsearch-model (6.0.0)
elasticsearch-rails (6.0.0)
minitest (= 5.10.1)

3 个答案:

答案 0 :(得分:2)

很高兴您找到了特定问题的根本原因。

我遇到了一个类似的问题,即用于elasticsearch的ruby-on-rails宝石。虽然映射都很好,但我确实得到了完全相同的错误消息。在这里留下我的答案,以便其他任何来这里的人都能获得更多帮助。

经过多次尝试和错误,最终发现原因是它在创建索引上超时。

如果将客户端超时更改为60秒(它失败了30秒),则它可以成功创建索引,而不会引起此间歇性错误。

connection_hash = {
      hosts: [ "localhost:9220" ]
      reload_connections: true
      adapter: :httpclient
      retry_on_failure: 2
      request_timeout: 60
}

es_connection_client = Elasticsearch::Client.new(connection_hash)

还发现了与此相关的问题,并在得到类似答案后将其关闭。 https://github.com/ankane/searchkick/issues/843#issuecomment-384136164

答案 1 :(得分:1)

我在多个规范中使用了时间冻结,因此创建一个与之前规范中的对象具有相同 created_at 时间的新对象导致了 resource_already_exists_exception 错误。稍微调整每个规范的时间戳以冻结解决了问题。

答案 2 :(得分:0)

我的模型映射错误。我使用type来代替index选项,这使ElasticSearch创建了多重映射。自6.4版以来,哪一个版本不可用(我想)。