common_grams 过滤器

edit

common_grams 过滤器是针对短语查询能更高效的使用停用词而设计的。 它与 shingles 过滤器类似(参见 查找相关词(寻找相关词)), 为每个相邻词对生成 ,用示例解释更为容易。

common_grams 过滤器根据 query_mode 设置的不同而生成不同输出结果:false (为索引使用) 或 true (为搜索使用),所以我们必须创建两个独立的分析器:

PUT /my_index
{
  "settings": {
    "analysis": {
      "filter": {
        "index_filter": { 
          "type":         "common_grams",
          "common_words": "_english_" 
        },
        "search_filter": { 
          "type":         "common_grams",
          "common_words": "_english_", 
          "query_mode":   true
        }
      },
      "analyzer": {
        "index_grams": { 
          "tokenizer":  "standard",
          "filter":   [ "lowercase", "index_filter" ]
        },
        "search_grams": { 
          "tokenizer": "standard",
          "filter":  [ "lowercase", "search_filter" ]
        }
      }
    }
  }
}

首先我们基于 common_grams 过滤器创建两个过滤器: index_filter 在索引时使用(此时 query_mode 的默认设置是 false ), search_filter 在查询时使用(此时 query_mode 的默认设置是 true )。

common_words 参数可以接受与 stopwords 参数同样的选项(参见 指定停用词 指定停用词(Specifying Stopwords) )。这个过滤器还可以接受参数 common_words_path ,使用存于文件里的常用词。

然后我们使用过滤器各创建一个索引时分析器和查询时分析器。

有了自定义分析器,我们可以创建一个字段在索引时使用 index_grams 分析器:

PUT /my_index/_mapping/my_type
{
  "properties": {
    "text": {
      "type":            "string",
      "analyzer":  "index_grams", 
      "search_analyzer": "standard" 
    }
  }
}

text 字段索引时使用 index_grams 分析器,但是在搜索时默认使用 standard 分析器,稍后我们会解释其原因。

索引时(At Index Time)

edit

如果我们对短语 The quick and brown fox 进行拆分,它生成如下词项:

Pos 1: the_quick
Pos 2: quick_and
Pos 3: and_brown
Pos 4: brown_fox

新的 index_grams 分析器生成以下词项:

Pos 1: the, the_quick
Pos 2: quick, quick_and
Pos 3: and, and_brown
Pos 4: brown
Pos 5: fox

所有的词项都是以 unigrams 形式输出的(the、quick 等等),但是如果一个词本身是常用词或者跟随着常用词,那么它同时还会在 unigram 同样的位置以 bigram 形式输出:the_quickquick_andand_brown

单字查询(Unigram Queries)

edit

因为索引包含 unigrams ,可以使用与其他字段相同的技术进行查询,例如:

GET /my_index/_search
{
  "query": {
    "match": {
      "text": {
        "query": "the quick and brown fox",
        "cutoff_frequency": 0.01
      }
    }
  }
}

上面这个查询字符串是通过为文本字段配置的 search_analyzer 分析器 --本例中使用的是 standard 分析器-- 进行分析的, 它生成的词项为: thequickandbrownfox

因为 text 字段的索引中包含与 standard 分析去生成的一样的 unigrams ,搜索对于任何普通字段都能正常工作。

二元语法短语查询(Bigram Phrase Queries)

edit

但是,当我们进行短语查询时,我们可以用专门的 search_grams 分析器让整个过程变得更高效:

GET /my_index/_search
{
  "query": {
    "match_phrase": {
      "text": {
        "query":    "The quick and brown fox",
        "analyzer": "search_grams" 
      }
    }
  }
}

对于短语查询,我们重写了默认的 search_analyzer 分析器,而使用 search_grams 分析器。

search_grams 分析器会生成以下词项:

Pos 1: the_quick
Pos 2: quick_and
Pos 3: and_brown
Pos 4: brown
Pos 5: fox

分析器排除了所有常用词的 unigrams,只留下常用词的 bigrams 以及低频的 unigrams。如 the_quick 这样的 bigrams 比单个词项 the 更为少见,这样有两个好处:

  • the_quick 的位置信息要比 the 的小得多,所以它读取磁盘更快,对系统缓存的影响也更小。
  • 词项 the_quick 没有 the 那么常见,所以它可以大量减少需要计算的文档。

两词短语(Two-Word Phrases)

edit

我们的优化可以更进一步,因为大多数的短语查询只由两个词组成,如果其中一个恰好又是常用词,例如:

GET /my_index/_search
{
  "query": {
    "match_phrase": {
      "text": {
        "query":    "The quick",
        "analyzer": "search_grams"
      }
    }
  }
}

那么 search_grams 分析器会输出单个语汇单元:the_quick 。这将原来昂贵的查询(查询 thequick )转换成了对单个词项的高效查找。