在 lunr 中,词干分析器被实现为管道功能。对文档进行索引时对文档中的每个单词执行管道函数,在搜索时对搜索查询中的每个单词执行管道函数。
对于在管道中工作的函数,它必须实现一个非常简单的接口。它需要接受单个字符串作为输入,并且必须以字符串作为输出进行响应。
因此,一个非常简单(且无用)的管道函数如下所示:
var simplePipelineFunction = function (word) {
return word
}
要真正使用这个管道功能,我们需要做两件事:
- 将其注册为管道函数,这允许 lunr 正确序列化和反序列化您的管道。
- 将其添加到您的索引管道。
看起来像这样:
// registering our pipeline function with the name 'simplePipelineFunction'
lunr.Pipeline.registerFunction(simplePipelineFunction, 'simplePipelineFunction')
var idx = lunr(function () {
// adding the pipeline function to our indexes pipeline
// when defining the pipeline
this.pipeline.add(simplePipelineFunction)
})
现在,您可以使用上述内容,并换出我们管道功能的实现。因此,它可以使用您找到的希腊词干分析器来词干该词,而不是仅仅返回该词不变,可能是这样的:
var myGreekStemmer = function (word) {
// I don't know how to use the greek stemmer, but I think
// its safe to assume it won't be that different than this
return greekStem(word)
}
使 lunr 适应英语以外的语言需要的不仅仅是添加你的词干分析器。lunr 的默认语言是英语,因此默认情况下,它包括专门用于英语的管道函数。英语和希腊语有很大的不同,您可能会在尝试使用英语默认值索引希腊语单词时遇到问题,因此我们需要执行以下操作:
- 用我们的语言特定词干替换默认词干分析器
- 删除对非拉丁字符效果不佳的默认修剪器
- 替换/删除默认的停用词过滤器,它不太可能在英语以外的语言上大量使用。
修剪器和停用词过滤器是作为管道函数实现的,因此对于词干分析器来说,实现特定于语言的过滤器是类似的。
因此,要为希腊语设置 lunr,您将拥有以下内容:
var idx = lunr(function () {
this.pipeline.after(lunr.stemmer, greekStemmer)
this.pipeline.remove(lunr.stemmer)
this.pipeline.after(lunr.trimmer, greekTrimmer)
this.pipeline.remove(lunr.trimmer)
this.pipeline.after(lunr.stopWordFilter, greekStopWordFilter)
this.pipeline.remove(lunr.stopWordFilter)
// define the index as normal
this.ref('id')
this.field('title')
this.field('body')
})
如需更多灵感,您可以查看优秀的lunr-languages项目,它有许多为 lunr 创建语言扩展的示例。你甚至可以提交一份希腊文!
编辑看起来我并不lunr.Pipeline
像我想象的那样了解API,没有replace
函数,而是我们只是在要删除的函数之后插入替换,然后将其删除。
编辑添加这个以帮助将来的其他人......事实证明问题出在lunr中令牌的外壳。lunr 想要将所有标记都视为小写,这是在tokenizer中完成的,没有任何可配置性。对于大多数语言处理函数来说,这不是问题,事实上,大多数假设单词是小写的。在这种情况下,由于希腊语词干的复杂性,希腊词干分析器仅对大写单词进行词干提取(我不是希腊语,因此无法评论词干提取的复杂程度)。一种解决方案是在调用希腊词干分析器之前转换为大写,然后在将标记传递到管道的其余部分之前转换回小写。