使用ElasticSearch的自动完成功能

dkqlctbz  于 2023-04-11  发布在  ElasticSearch
关注(0)|答案(3)|浏览(151)

我有以下文件的ElasticSearch索引,我想在指定的字段有一个自动完成功能:
Map:https://gist.github.com/anonymous/0609b1d110d91dceb9a90faa76d1d5d4
用途:
我的查询是前缀类型的形式,例如“sta”,“星星”,“star w”..“start war”等,带有附加的过滤器,如tags =“science fiction”。此外,还有查询可以匹配其他字段,如描述,演员(在演员表字段中,而不是嵌套的)。我还想知道它匹配的字段。
我研究了两种方法来做到这一点,但没有一种方法似乎可以解决上面的用例:
1)建议自动完成:
https://www.elastic.co/guide/en/elasticsearch/reference/1.7/search-suggesters-completion.html
有了这个,似乎我必须添加另一个名为“建议”的字段来复制数据,这是不可取的。
2)使用前缀过滤器/查询:
https://www.elastic.co/guide/en/elasticsearch/reference/1.7/query-dsl-prefix-filter.html
这返回整个文档而不是精确匹配的项。
是否有一个干净的方法来实现这一点,请提供建议。

tyu7yeag

tyu7yeag1#

不要单独创建Map,直接将数据插入到索引中。它将为此创建默认Map。使用下面的查询进行自动完成。

GET /netflix/movie/_search
{
"query": {
    "query_string": {
        "query": "sta*"
    }
  }
}
z18hc3ub

z18hc3ub2#

我认为completion suggester将是最干净的方式,但如果这是不可取的,你可以使用aggregations的名称字段。
这是一个示例索引(我假设您使用的是问题中的ES1.7

PUT netflix
{
  "settings": {
    "analysis": {
      "analyzer": {
        "prefix_analyzer": {
          "tokenizer": "keyword",
          "filter": [
            "lowercase",
            "trim",
            "edge_filter"
          ]
        },
        "keyword_analyzer": {
          "tokenizer": "keyword",
          "filter": [
            "lowercase",
            "trim"
          ]
        }
      },
      "filter": {
        "edge_filter": {
          "type": "edge_ngram",
          "min_gram": 1,
          "max_gram": 20
        }
      }
    }
  },
  "mappings": {
    "movie":{
      "properties": {
        "name":{
          "type": "string",
          "fields": {
            "prefix":{
            "type":"string",
            "index_analyzer" : "prefix_analyzer",
            "search_analyzer" : "keyword_analyzer"
            },
            "raw":{
              "type": "string",
              "analyzer": "keyword_analyzer"
            }
          }
        },
        "tags":{
          "type": "string", "index": "not_analyzed"
        }
      }
    }
  }
}

使用multi-fieldsname 字段以不同的方式进行分析。name.prefix 使用keyword tokenizeredge ngram filter,以便字符串 * 星星wars* 可以分解为 sststa 等。但是在搜索时,使用 keyword_analyzer,以便搜索查询不会分解为多个小标记。name.raw 将用于聚合。
以下查询将给予前10个建议。

GET netflix/movie/_search
{
  "query": {
    "filtered": {
      "filter": {
        "term": {
          "tags": "sci-fi"
        }
      },
      "query": {
        "match": {
          "name.prefix": "sta"
        }
      }
    }
  },
  "size": 0,
  "aggs": {
    "unique_movie_name": {
      "terms": {
        "field": "name.raw",
        "size": 10
      }
    }
  }
}

结果会是

"aggregations": {
      "unique_movie_name": {
         "doc_count_error_upper_bound": 0,
         "sum_other_doc_count": 0,
         "buckets": [
            {
               "key": "star trek",
               "doc_count": 1
            },
            {
               "key": "star wars",
               "doc_count": 1
            }
         ]
      }
   }

更新

我认为你可以使用highlighting来实现这个目的。突出显示部分会让你看到整个单词和它匹配的字段。你也可以使用inner hits和突出显示来获得嵌套的文档。

{
  "query": {
    "query_string": {
      "query": "sta*"
    }
  },
  "_source": false,
  "highlight": {
    "fields": {
      "*": {}
    }
  }
}
a5g8bdjr

a5g8bdjr3#

你可以使用小写过滤器的弹性索引。这将帮助您搜索大写字母以及。
使用以下设置创建文档

PUT lowercase_example
{
  "settings": {
    "analysis": {
      "analyzer": {
        "whitespace_lowercase": {
          "tokenizer": "whitespace",
          "filter": [ "lowercase" ]
        }
      }
    }
  },
 "mappings": {
    "properties": {
      "field1": { "type": "text" }
    }
  }
}

现在,当你搜索时,你会得到这两个字段,包括小写和大写

相关问题