【问题标题】:Google style autocomplete & autocorrection with elasticsearch谷歌风格的自动完成和自动更正与弹性搜索
【发布时间】:2016-06-07 23:08:40
【问题描述】:

我正在尝试使用 elasticsearch 实现谷歌风格的自动完成和自动更正。

映射:

POST music
{
  "settings": {
    "analysis": {
      "filter": {
        "nGram_filter": {
          "type": "nGram",
          "min_gram": 2,
          "max_gram": 20,
          "token_chars": [
            "letter",
            "digit",
            "punctuation",
            "symbol"
          ]
        }
      },
      "analyzer": {
        "nGram_analyzer": {
          "type": "custom",
          "tokenizer": "whitespace",
          "filter": [
            "lowercase",
            "asciifolding",
            "nGram_filter"
          ]
        },
        "whitespace_analyzer": {
          "type": "custom",
          "tokenizer": "whitespace",
          "filter": [
            "lowercase",
            "asciifolding"
          ]
        }
      }
    }
  },
  "mappings": {
    "song": {
      "properties": {
        "song_field": {
          "type": "string",
          "analyzer": "nGram_analyzer",
          "search_analyzer": "whitespace_analyzer"
        },
        "suggest": {
          "type": "completion",
          "analyzer": "simple",
          "search_analyzer": "simple",
          "payloads": true
        }
      }
    }
  }
}

文档:

POST music/song
{
  "song_field" : "beautiful queen",
  "suggest" : "beautiful queen"
}

POST music/song
{
  "song_field" : "beautiful",
  "suggest" : "beautiful"
}

我希望当用户输入:“beaatiful q”时,他会得到类似beautiful queen 的信息(beaatiful 被纠正为 beautiful,q 被完成为queen)。

我尝试了以下查询:

POST music/song/_search?search_type=dfs_query_then_fetch
{
  "size": 10,
  "suggest": {
    "didYouMean": {
      "text": "beaatiful q",
      "completion": {
        "field": "suggest"
      }
    }
  },
  "query": {
    "match": {
      "song_field": {
        "query": "beaatiful q",
         "fuzziness": 2
      }
    }
  }
}

很遗憾,Completion suggester 不允许出现任何拼写错误,所以我收到了这样的回复:

"suggest": {
    "didYouMean": [
      {
        "text": "beaatiful q",
        "offset": 0,
        "length": 11,
        "options": []
      }
    ]
  }

此外,搜索给了我这些结果(漂亮的排名更高,虽然用户开始写“女王”):

"hits": [
      {
        "_index": "music",
        "_type": "song",
        "_id": "AVUj4Y5NancUpEdFLeLo",
        "_score": 0.51315063,
        "_source": {
          "song_field": "beautiful"
          "suggest": "beautiful"
        }
      },
      {
        "_index": "music",
        "_type": "song",
        "_id": "AVUj4XFAancUpEdFLeLn",
        "_score": 0.32071912,
        "_source": {
          "song_field": "beautiful queen"
          "suggest": "beautiful queen"
        }
      }
    ]

更新!!!

我发现我可以将模糊查询与完成提示器一起使用,但现在查询时我没有收到任何建议(模糊只支持 2 编辑距离):

POST music/song/_search
{
  "size": 10,
  "suggest": {
    "didYouMean": {
      "text": "beaatefal q",
      "completion": {
        "field": "suggest",
        "fuzzy" : {
                "fuzziness" : 2
            }
      }
    }
  }
}

我仍然希望“beautiful queen”作为建议响应。

【问题讨论】:

  • 在搜索部分,如果你想匹配多个单词,你应该使用match_phrase。但是,如果用户输入beaatiful q,我不明白您如何在搜索部分输入beautiful q...
  • @Val 当用户发送 'beaatiful q' 我希望收到 'beautiful queen' 作为建议。
  • 我只是在评论搜索部分,而不是建议部分。我的问题是,如果用户输入beaatiful q,你可以在建议部分输入beaatiful q,在搜索部分输入beautiful q
  • @Val 这是一个错字。我已经编辑了问题。
  • 你试过match_phrase而不是match吗?

标签: elasticsearch


【解决方案1】:

当您想提供 2 个或更多单词作为搜索建议时,我发现(很难)在 Elasticsearch 中使用 ngrams 或 edgengrams 是不值得的。

使用 Shingles token filtershingles analyzer 将为您提供多词短语,如果您将其与 match_phrase_prefix 结合使用,它应该会为您提供所需的功能。

基本上是这样的:

    PUT /my_index
{
    "settings": {
        "number_of_shards": 1,  
        "analysis": {
            "filter": {
                "my_shingle_filter": {
                    "type":             "shingle",
                    "min_shingle_size": 2, 
                    "max_shingle_size": 2, 
                    "output_unigrams":  false   
                }
            },
            "analyzer": {
                "my_shingle_analyzer": {
                    "type":             "custom",
                    "tokenizer":        "standard",
                    "filter": [
                        "lowercase",
                        "my_shingle_filter" 
                    ]
                }
            }
        }
    }
}

别忘了做你的映射:

{
"my_type": {
    "properties": {
        "title": {
            "type": "string",
            "fields": {
                "shingles": {
                    "type":     "string",
                    "analyzer": "my_shingle_analyzer"
                }
            }
        }
    }
}

}

Ngrams 和 edgengrams 将标记单个字符,而 Shingles 分析器和过滤器将字母分组(生成单词)并提供更有效的生成和搜索短语的方法。我花了很多时间弄乱上面的 2,直到我看到提到的带状疱疹并阅读了它。好多了。

【讨论】:

  • 没有给出预期的结果
猜你喜欢
  • 2011-09-19
  • 1970-01-01
  • 2012-01-04
  • 2023-04-09
  • 2019-08-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多