Elasticsearch:使用路径层次分词器 — Path Hierarchy Tokenizer

1,693 阅读7分钟

想象一下你的文档具有层次结构特征并且你想搜索层次结构级别的情况,我相信 Path Hierarchy Tokenizer 是你需要了解的分词器。Path_hierarchy 分词器采用像文件系统路径这样的层次结构值,在路径分隔符上拆分,并为树中的每个组件发出一个术语。一个简单的例子:



1.  POST _analyze
2.  {
3.    "tokenizer": "path_hierarchy",
4.    "text": "/one/two/three"
5.  }


上面的输出为:



1.  {
2.    "tokens": [
3.      {
4.        "token": "/one",
5.        "start_offset": 0,
6.        "end_offset": 4,
7.        "type": "word",
8.        "position": 0
9.      },
10.      {
11.        "token": "/one/two",
12.        "start_offset": 0,
13.        "end_offset": 8,
14.        "type": "word",
15.        "position": 0
16.      },
17.      {
18.        "token": "/one/two/three",
19.        "start_offset": 0,
20.        "end_offset": 14,
21.        "type": "word",
22.        "position": 0
23.      }
24.    ]
25.  }


配置

条目描述
delimiter用作路径分隔符的字符。 默认为 /
replacement用于分隔符的可选替换字符。 默认为 delimiter 所定义的值
buffer_size单次读取到术语缓冲区的字符数。 默认为 1024。术语缓冲区将按此大小增长,直到所有文本都被消耗掉。 建议不要更改此设置。
reverse如果设置为 true,它会以相反的顺序发出分词。 默认为 false。
skip要跳过的初始分词数。 默认为 0。

配置例子

在此示例中,我们将 path_hierarchy 分词器配置为以 - 字符进行拆分,并用 / 替换它们。 跳过前两个分词:



1.  PUT my-index-000001
2.  {
3.    "settings": {
4.      "analysis": {
5.        "analyzer": {
6.          "my_analyzer": {
7.            "tokenizer": "my_tokenizer"
8.          }
9.        },
10.        "tokenizer": {
11.          "my_tokenizer": {
12.            "type": "path_hierarchy",
13.            "delimiter": "-",
14.            "replacement": "/",
15.            "skip": 2
16.          }
17.        }
18.      }
19.    }
20.  }


我们使用如下的例子来进行测试:



1.  POST my-index-000001/_analyze
2.  {
3.    "analyzer": "my_analyzer",
4.    "text": "one-two-three-four-five"
5.  }


上面命令显示的结果为:



1.  {
2.    "tokens": [
3.      {
4.        "token": "/three",
5.        "start_offset": 7,
6.        "end_offset": 13,
7.        "type": "word",
8.        "position": 0
9.      },
10.      {
11.        "token": "/three/four",
12.        "start_offset": 7,
13.        "end_offset": 18,
14.        "type": "word",
15.        "position": 0
16.      },
17.      {
18.        "token": "/three/four/five",
19.        "start_offset": 7,
20.        "end_offset": 23,
21.        "type": "word",
22.        "position": 0
23.      }
24.    ]
25.  }


从上面的结果中,我们可以看出来:

  • 它跳过了前面的两个分词 one 及 two
  • 分词是以 - 字符为分界符进行拆分的
  •  - 被 / 所代替

我们还可以进行如下的配置来试试:



1.  PUT my-index-000001
2.  {
3.    "settings": {
4.      "analysis": {
5.        "analyzer": {
6.          "my_analyzer": {
7.            "tokenizer": "my_tokenizer"
8.          }
9.        },
10.        "tokenizer": {
11.          "my_tokenizer": {
12.            "type": "path_hierarchy",
13.            "delimiter": "-",
14.            "replacement": "/",
15.            "skip": 2,
16.            "reverse": true
17.          }
18.        }
19.      }
20.    }
21.  }


在上面,我们把 reverse 选项设置为 true。运行上面的命令,并以如下的实例来进行测试:



1.  POST my-index-000001/_analyze
2.  {
3.    "analyzer": "my_analyzer",
4.    "text": "one-two-three-four-five"
5.  }


上面的命令显示的结果为:



1.  {
2.    "tokens": [
3.      {
4.        "token": "one/two/three/",
5.        "start_offset": 0,
6.        "end_offset": 14,
7.        "type": "word",
8.        "position": 0
9.      },
10.      {
11.        "token": "two/three/",
12.        "start_offset": 4,
13.        "end_offset": 14,
14.        "type": "word",
15.        "position": 0
16.      },
17.      {
18.        "token": "three/",
19.        "start_offset": 8,
20.        "end_offset": 14,
21.        "type": "word",
22.        "position": 0
23.      }
24.    ]
25.  }


很显然,它和之前的那个还是有所不同的。

详细示例

path_hierarchy 分词器的一个常见用例是按文件路径过滤结果。 如果将文件路径与数据一起索引,使用 path_hierarchy 分词器分析路径允许按文件路径字符串的不同部分过滤结果。

此示例将索引配置为具有两个自定义分析器,并将这些分析器应用于将存储文件名的 file_path 文本字段的多字段。 两个分析器之一使用反向分词。 然后索引一些示例文档以表示两个不同用户的照片文件夹中照片的一些文件路径。

我们首先来定义索引:



1.  PUT file-path-test
2.  {
3.    "settings": {
4.      "analysis": {
5.        "analyzer": {
6.          "custom_path_tree": {
7.            "tokenizer": "custom_hierarchy"
8.          },
9.          "custom_path_tree_reversed": {
10.            "tokenizer": "custom_hierarchy_reversed"
11.          }
12.        },
13.        "tokenizer": {
14.          "custom_hierarchy": {
15.            "type": "path_hierarchy",
16.            "delimiter": "/"
17.          },
18.          "custom_hierarchy_reversed": {
19.            "type": "path_hierarchy",
20.            "delimiter": "/",
21.            "reverse": "true"
22.          }
23.        }
24.      }
25.    },
26.    "mappings": {
27.      "properties": {
28.        "file_path": {
29.          "type": "text",
30.          "fields": {
31.            "tree": {
32.              "type": "text",
33.              "analyzer": "custom_path_tree"
34.            },
35.            "tree_reversed": {
36.              "type": "text",
37.              "analyzer": "custom_path_tree_reversed"
38.            }
39.          }
40.        }
41.      }
42.    }
43.  }


我们使用如下的一些文档来进行测试:



1.  POST file-path-test/_bulk
2.  { "index" : {"_id" : "1" } }
3.  { "file_path" : "/User/alice/photos/2017/05/16/my_photo1.jpg" }
4.  { "index" : {"_id" : "2" } }
5.  { "file_path" : "/User/alice/photos/2017/05/16/my_photo2.jpg" }
6.  { "index" : {"_id" : "3" } }
7.  { "file_path" : "/User/alice/photos/2017/05/16/my_photo3.jpg" }
8.  { "index" : {"_id" : "4" } }
9.  { "file_path" : "/User/alice/photos/2017/05/15/my_photo1.jpg" }
10.  { "index" : {"_id" : "5" } }
11.  { "file_path" : "/User/bob/photos/2017/05/16/my_photo1.jpg" }


针对文本字段搜索特定文件路径字符串与所有示例文档相匹配,Bob 的文档排名最高,因为 bob 也是标准分析器创建的提高 Bob 文档相关性的术语之一。



1.  GET file-path-test/_search?filter_path=**.hits
2.  {
3.    "query": {
4.      "match": {
5.        "file_path": "/User/bob/photos/2017/05"
6.      }
7.    }
8.  }




1.  {
2.    "hits": {
3.      "hits": [
4.        {
5.          "_index": "file-path-test",
6.          "_id": "5",
7.          "_score": 1.7343397,
8.          "_source": {
9.            "file_path": "/User/bob/photos/2017/05/16/my_photo1.jpg"
10.          }
11.        },
12.        {
13.          "_index": "file-path-test",
14.          "_id": "1",
15.          "_score": 0.34804547,
16.          "_source": {
17.            "file_path": "/User/alice/photos/2017/05/16/my_photo1.jpg"
18.          }
19.        },
20.        {
21.          "_index": "file-path-test",
22.          "_id": "2",
23.          "_score": 0.34804547,
24.          "_source": {
25.            "file_path": "/User/alice/photos/2017/05/16/my_photo2.jpg"
26.          }
27.        },
28.        {
29.          "_index": "file-path-test",
30.          "_id": "3",
31.          "_score": 0.34804547,
32.          "_source": {
33.            "file_path": "/User/alice/photos/2017/05/16/my_photo3.jpg"
34.          }
35.        },
36.        {
37.          "_index": "file-path-test",
38.          "_id": "4",
39.          "_score": 0.34804547,
40.          "_source": {
41.            "file_path": "/User/alice/photos/2017/05/15/my_photo1.jpg"
42.          }
43.        }
44.      ]
45.    }
46.  }


在上述的搜索中,它并没有使用到 path_hierarchy 分词器。这个是使用标准的分析器二得到的结果。

使用 file_path.tree 字段可以很简单地匹配或过滤具有特定目录中存在的文件路径的文档。



1.  GET file-path-test/_search?filter_path=**.hits
2.  {
3.    "query": {
4.      "term": {
5.        "file_path.tree": "/User/alice/photos/2017/05/16"
6.      }
7.    }
8.  }


上面命令显示的结果为:



1.  {
2.    "hits": {
3.      "hits": [
4.        {
5.          "_index": "file-path-test",
6.          "_id": "1",
7.          "_score": 0.83005464,
8.          "_source": {
9.            "file_path": "/User/alice/photos/2017/05/16/my_photo1.jpg"
10.          }
11.        },
12.        {
13.          "_index": "file-path-test",
14.          "_id": "2",
15.          "_score": 0.83005464,
16.          "_source": {
17.            "file_path": "/User/alice/photos/2017/05/16/my_photo2.jpg"
18.          }
19.        },
20.        {
21.          "_index": "file-path-test",
22.          "_id": "3",
23.          "_score": 0.83005464,
24.          "_source": {
25.            "file_path": "/User/alice/photos/2017/05/16/my_photo3.jpg"
26.          }
27.        }
28.      ]
29.    }
30.  }


使用此分词器的反向参数,还可以从文件路径的另一端进行匹配,例如单个文件名或深层子目录。 以下示例显示了通过配置为在映射中使用反向参数的 file_path.tree_reversed 字段在任何目录中搜索所有名为 my_photo1.jpg 的文件。



1.  GET file-path-test/_search?filter_path=**.hits
2.  {
3.    "query": {
4.      "term": {
5.        "file_path.tree_reversed": {
6.          "value": "my_photo1.jpg"
7.        }
8.      }
9.    }
10.  }




1.  {
2.    "hits": {
3.      "hits": [
4.        {
5.          "_index": "file-path-test",
6.          "_id": "1",
7.          "_score": 0.839499,
8.          "_source": {
9.            "file_path": "/User/alice/photos/2017/05/16/my_photo1.jpg"
10.          }
11.        },
12.        {
13.          "_index": "file-path-test",
14.          "_id": "4",
15.          "_score": 0.839499,
16.          "_source": {
17.            "file_path": "/User/alice/photos/2017/05/15/my_photo1.jpg"
18.          }
19.        },
20.        {
21.          "_index": "file-path-test",
22.          "_id": "5",
23.          "_score": 0.839499,
24.          "_source": {
25.            "file_path": "/User/bob/photos/2017/05/16/my_photo1.jpg"
26.          }
27.        }
28.      ]
29.    }
30.  }


当与其他类型的搜索结合使用时,能够使用文件路径进行过滤也很有用,例如本例中查找具有 16 且也必须位于 Alice 的照片目录中的任何文件路径。



1.  GET file-path-test/_search?filter_path=**.hits
2.  {
3.    "query": {
4.      "bool" : {
5.        "must" : {
6.          "match" : { "file_path" : "16" }
7.        },
8.        "filter": {
9.          "term" : { "file_path.tree" : "/User/alice" }
10.        }
11.      }
12.    }
13.  }


上述命令返回的结果为:



1.  {
2.    "hits": {
3.      "hits": [
4.        {
5.          "_index": "file-path-test",
6.          "_id": "1",
7.          "_score": 0.2876821,
8.          "_source": {
9.            "file_path": "/User/alice/photos/2017/05/16/my_photo1.jpg"
10.          }
11.        },
12.        {
13.          "_index": "file-path-test",
14.          "_id": "2",
15.          "_score": 0.2876821,
16.          "_source": {
17.            "file_path": "/User/alice/photos/2017/05/16/my_photo2.jpg"
18.          }
19.        },
20.        {
21.          "_index": "file-path-test",
22.          "_id": "3",
23.          "_score": 0.2876821,
24.          "_source": {
25.            "file_path": "/User/alice/photos/2017/05/16/my_photo3.jpg"
26.          }
27.        }
28.      ]
29.    }
30.  }


更多阅读:Elasticsearch:使用 Path Hierarchy Tokenizer 搜索层次结构