概述
在构建好自己的分词器时,测试分词器是否按照我们的期望执行是很有用的。这就是Analyze API发挥作用的地方。
测试内置分词器
为了开始使用Analyze API,我们可以进行测试,看看内置分词器如何分析一段文本
var analyzeResponse = client.Indices.Analyze(a => a
.Analyzer("standard") // 使用内置的standard分词器
.Text("F# is THE SUPERIOR language :)")
);
Elasticsearch将返回如下的分词结果:
{
"tokens": [
{
"token": "f",
"start_offset": 0,
"end_offset": 1,
"type": "<ALPHANUM>",
"position": 0
},
{
"token": "is",
"start_offset": 3,
"end_offset": 5,
"type": "<ALPHANUM>",
"position": 1
},
{
"token": "the",
"start_offset": 6,
"end_offset": 9,
"type": "<ALPHANUM>",
"position": 2
},
{
"token": "superior",
"start_offset": 10,
"end_offset": 18,
"type": "<ALPHANUM>",
"position": 3
},
{
"token": "language",
"start_offset": 19,
"end_offset": 27,
"type": "<ALPHANUM>",
"position": 4
}
]
}
它是由NEST反序列化AnalyzeResponse
的一个实例,我们可以使用如下:
foreach (var analyzeToken in analyzeResponse.Tokens)
{
Console.WriteLine($"{analyzeToken.Token}");
}
在使用内置的standard
分词器进行测试时,我们注意到:
F#
被标记为了f
- 停用词
is
,the
被包含了 - “superior”也包括在内,但我们也想把”great”作为”superior”的同义词
接下来,我们将看看如何测试内置分词组件的组合,然后构建一个满足我们需求的分词器
测试内置分词组合
瞬态分词器可以由内置的分词组件组成,以测试分词配置
var analyzeResponse = client.Indices.Analyze(a => a
.Tokenizer("standard")
.Filter("lowercase", "stop")
.Text("F# is THE SUPERIOR language :)")
);
Elasticsearch返回的测试分词结果为:
{
"tokens": [
{
"token": "f",
"start_offset": 0,
"end_offset": 1,
"type": "<ALPHANUM>",
"position": 0
},
{
"token": "superior",
"start_offset": 10,
"end_offset": 18,
"type": "<ALPHANUM>",
"position": 3
},
{
"token": "language",
"start_offset": 19,
"end_offset": 27,
"type": "<ALPHANUM>",
"position": 4
}
]
}
这时的分词结果删除了停词,但仍然将F#
标记为“f”,而且没有”superior”的同义词”great”。
让我们构建一个带有附加组件的自定义分词器来解决这个问题。
测试自定义分词器
可以在索引中创建自定义分词器,既可以在创建索引时创建,也可以通过更新现有索引的设置来创建。
当添加到现有索引时,需要先关闭它。
在本例中,我们将向现有索引添加一个自定义分词器。首先,我们需要关闭索引。
client.Indices.Close("analysis-index");
现在,我们可以更新设置以添加分词器
client.Indices.UpdateSettings("analysis-index", i => i
.IndexSettings(s => s
.Analysis(a => a
.CharFilters(cf => cf
.Mapping("my_char_filter", m => m
.Mappings("F# => FSharp")
)
)
.TokenFilters(tf => tf
.Synonym("my_synonym", sf => sf
.Synonyms("superior, great")
)
)
.Analyzers(an => an
.Custom("my_analyzer", ca => ca
.Tokenizer("standard")
.CharFilters("my_char_filter")
.Filters("lowercase", "stop", "my_synonym")
)
)
)
)
);
然后再次打开索引。在这里,我们还要等待5秒钟,以使索引的状态变为绿色
client.Indices.Open("analysis-index");
client.Cluster.Health("analysis-index",h => h
.WaitForStatus(WaitForStatus.Green)
.Timeout(TimeSpan.FromSeconds(5))
);
索引打开并准备就绪后,让我们测试分词器
var analyzeResponse = client.Indices.Analyze(a => a
.Index("analysis-index")
.Analyzer("my_analyzer")
.Text("F# is THE SUPERIOR language :)")
);
Elasticsearch的分词测试结果为:
{
"tokens": [
{
"token": "fsharp",
"start_offset": 0,
"end_offset": 2,
"type": "<ALPHANUM>",
"position": 0
},
{
"token": "superior",
"start_offset": 10,
"end_offset": 18,
"type": "<ALPHANUM>",
"position": 3
},
{
"token": "great",
"start_offset": 10,
"end_offset": 18,
"type": "SYNONYM",
"position": 3
},
{
"token": "language",
"start_offset": 19,
"end_offset": 27,
"type": "<ALPHANUM>",
"position": 4
}
]
}
从测试结果来看,已经得到了我们期望的分词结果。
测试字段的分词器
还可以为给定的字段类型映射测试分词器。给定一个用以下设置和映射创建的索引
client.Indices.Create("project-index", i => i
.Settings(s => s
.Analysis(a => a
.CharFilters(cf => cf
.Mapping("my_char_filter", m => m
.Mappings("F# => FSharp")
)
)
.TokenFilters(tf => tf
.Synonym("my_synonym", sf => sf
.Synonyms("superior, great")
)
)
.Analyzers(an => an
.Custom("my_analyzer", ca => ca
.Tokenizer("standard")
.CharFilters("my_char_filter")
.Filters("lowercase", "stop", "my_synonym")
)
)
)
)
.Map<Project>(mm => mm
.Properties(p => p
.Text(t => t
.Name(n => n.Name)
.Analyzer("my_analyzer")
)
)
)
);
名称字段上的分词器测试如下:
var analyzeResponse = client.Indices.Analyze(a => a
.Index("project-index")
.Field<Project, string>(f => f.Name)
.Text("F# is THE SUPERIOR language :)")
);
发表评论
登录用户才能发表评论, 请 登 录 或者 注册