为什么Postgres全文搜索和Elasticsearch对结果的排名不同?

时间:2017-08-21 02:46:35

标签: ruby postgresql elasticsearch full-text-search searchkick

我想知道,在将Postgres的全文搜索与Elasticsearch进行比较时,有实施全文搜索经验的人是否可以对我的奇怪结果有所了解。

我使用一对Rails应用程序来测试它们,每个都有相同的模型(但是有不同的宝石,用于pg测试的'textacular',用于es测试的'searchkick')和相同的测试数据:

# seeds.rb

def make_post(body)
  {
    title: 'A Post About Fruits',
    body: body,
    num_likes: 0
  }
end

Post.destroy_all

Post.create([
  make_post('I like apples.'),
  make_post('I like bananas.'),
  make_post('I like apples and bananas.'),
  make_post('I like oranges.'),
  make_post('I like.')
])

但是当我对它们进行大量搜索时,结果似乎对Postgres更有意义,有时候对Elasticsearch更有意义,并且它们在行为上经常相互矛盾。在下面的结果中,我列出了为每个搜索词返回的前两个帖子,或者一个帖子或零,如果这是所有返回的:

  

搜索:

     

'苹果':

     

PG:   “我喜欢苹果。”   “我喜欢苹果和香蕉。”

     

ES:

     
      
  1. '我喜欢苹果和香蕉。'
  2.   
  3. '我喜欢苹果。'
  4.         

    '香蕉':

         

    PG:   “我喜欢香蕉。”   “我喜欢苹果和香蕉。”

         

    ES:   “我喜欢香蕉。”   “我喜欢苹果和香蕉。”

         

    'apples and':

         

    PG:   “我喜欢苹果。”   “我喜欢苹果和香蕉。”

         

    ES:   “我喜欢苹果和香蕉。”

         “苹果和香蕉”:

         

    PG:   “我喜欢苹果和香蕉。”

         

    ES:   “我喜欢苹果和香蕉。”

         

    '我喜欢苹果。':

         

    PG:   “我喜欢苹果。”   “我喜欢苹果和香蕉。”

         

    ES:   “我喜欢苹果和香蕉。”   “我喜欢苹果。”

         

    '应用':

         

    pg:没有结果

         

    ES:   “我喜欢苹果和香蕉。”   “我喜欢苹果。”

         

    '申请':

         

    PG:   “我喜欢苹果。”   “我喜欢苹果和香蕉。”

         

    ES:   “我喜欢苹果和香蕉。”   “我喜欢苹果。”

我不得不承认,这是默认设置,我没有调整或使用自定义查询语法(做AND vs OR等)。

1 个答案:

答案 0 :(得分:2)

您从Elasticsearch获得了奇怪的结果,因为某些统计信息是在单个分片中计算的,而不是在整个索引中计算的。通常情况下这很好,因为大多数文档集都很大,但是当您在分片中只有一些文档时,这些统计数据并没有多大意义。在你的情况下,我认为有问题的统计数据是avgFieldLength,这有助于tfNorm得分。尝试使用一个分片创建一个新索引:

PUT /testindex
{
  "settings": {
    "index": {
      "number_of_shards": 1
    }
  }
}


POST /testindex/doc/1
{
  "body": "I like apples."
}


POST /testindex/doc/2
{
  "body": "I like apples and bananas."
}

然后查询:

POST /testindex
{
  "query": {
    "query_string": {
      "query": "apples"
    }
 }

然后你应该看到等级:

  1. 我喜欢苹果。
  2. 我喜欢苹果和香蕉。
  3. 如果您想弄清楚排名发生了什么,可以使用说明:

    POST /testindex
    {
      "explain": true,
      "query": {
        "query_string": {
          "query": "apples"
        }
     }
    

    所有这一切,你不应该期望postgres搜索排名与弹性搜索排名相匹配。 Elasticsearch使用标准化的tf-idf分数,而postgres不考虑文档频率或文档长度。有关详细信息,请参阅此问题:Does PostgreSQL use tf-idf?