一尘不染

Elasticsearch在分析字段上的精确匹配

elasticsearch

有没有办法让ElasticSearch在分析的字段上识别完全匹配?理想情况下,我想小写,标记化,词干化,甚至对我的文档进行语音化,然后让查询提取“精确”匹配项。

我的意思是,如果我索引“汉堡包”和“汉堡包”,它们将被分析为[“汉堡包”,“小圆面包”]和[“汉堡包”]。如果我搜索“汉堡”,它将仅返回“汉堡”文档,因为这是“完全匹配”。

我尝试使用关键字标记器,但不会阻止各个标记。我是否需要做一些事情以确保令牌数量相等?

我熟悉多字段并使用“ not_analyzed”类型,但这比我要查找的要严格。我想要精确匹配,后期分析。


阅读 837

收藏
2020-06-22

共1个答案

一尘不染

混合使用带状词标记器和词干以及您需要的其他任何东西。添加一个子字段,该子字段token_count将计算该字段中令牌的数量。

在搜索时,您需要添加一个额外的过滤器,以使索引中的令牌数与搜索文本中具有的令牌数相匹配。在执行实际搜索时,您将需要一个额外的步骤,该步骤应该计算搜索字符串中的标记。之所以这样,是因为带状疱疹会创建标记的多个排列,并且您需要确保其与搜索文本的大小匹配。

尝试这样做,只是为了给您一个想法:

{
  "settings": {
    "analysis": {
      "filter": {
        "filter_shingle": {
          "type": "shingle",
          "max_shingle_size": 10,
          "min_shingle_size": 2,
          "output_unigrams": true
        },
        "filter_stemmer": {
          "type": "porter_stem",
          "language": "_english_"
        }
      },
      "analyzer": {
        "ShingleAnalyzer": {
          "tokenizer": "standard",
          "filter": [
            "lowercase",
            "snowball",
            "filter_stemmer",
            "filter_shingle"
          ]
        }
      }
    }
  },
  "mappings": {
    "test": {
      "properties": {
        "text": {
          "type": "string",
          "analyzer": "ShingleAnalyzer",
          "fields": {
            "word_count": {
              "type": "token_count",
              "store": "yes",
              "analyzer": "ShingleAnalyzer"
            }
          }
        }
      }
    }
  }
}

和查询:

{
  "query": {
    "filtered": {
      "query": {
        "match_phrase": {
          "text": {
            "query": "HaMbUrGeRs BUN"
          }
        }
      },
      "filter": {
        "term": {
          "text.word_count": "2"
        }
      }
    }
  }
}

shingles过滤器是在这里非常重要,因为它可以创建令牌的组合。不仅如此,这些是保留顺序或令牌的组合。Imo,在这里要实现的最困难的要求是更改令牌(填充,降低外壳等),并重新组合原始文本。除非您定义自己的“串联”过滤器,否则我认为除了使用shingles过滤器之外没有其他方法。

但是shingles还有另一个问题:它会创建不需要的组合。对于像"Hamburgers buns in Los Angeles"您这样的文本,最终会有一长串带状疱疹:

          "angeles",
          "buns",
          "buns in",
          "buns in los",
          "buns in los angeles",
          "hamburgers",
          "hamburgers buns",
          "hamburgers buns in",
          "hamburgers buns in los",
          "hamburgers buns in los angeles",
          "in",
          "in los",
          "in los angeles",
          "los",
          "los angeles"

如果您只对 完全
匹配的文档感兴趣,则仅当您搜索“洛杉矶的汉堡包”时(而不与“洛杉矶的任何汉堡包”类似),以上文档才匹配,那么您需要过滤长长的带状疱疹的方法。我看的方式是使用word_count

2020-06-22