对lunr.js的希腊语言支持

时间:2016-09-06 08:35:29

标签: javascript full-text-search static-site non-latin lunrjs

在lunr中为希腊词语注册新的词干分析器功能并不像预期的那样工作。 here是我在codepen上的代码。我没有收到任何错误,函数stemWord()在单独使用时工作正常,但它无法阻止lunr中的单词。 下面是代码示例:

function stemWord(w) {
// code that returns the stemmed word
};

// create the new function
greekStemmer = function (token) {
    return stemWord(token);
};

// register it with lunr.Pipeline, this allows you to still serialise the index
lunr.Pipeline.registerFunction(greekStemmer, 'greekStemmer')

  var index = lunr(function () {
    this.field('title', {boost: 10})
    this.field('body')
    this.ref('id')

    this.pipeline.remove(lunr.trimmer) // it doesn't work well with non-latin characters
    this.pipeline.add(greekStemmer)
  })

    index.add({
    id: 1,
    title: 'ΚΑΠΟΙΟΣ',
    body: 'Foo foo foo!'
  })

  index.add({
    id: 2,
    title: 'ΚΑΠΟΙΕΣ',
    body: 'Bar bar bar!'
  })


  index.add({
    id: 3,
    title: 'ΤΙΠΟΤΑ',
    body: 'Bar bar bar!'
  })

1 个答案:

答案 0 :(得分:2)

在lunr中,一个词干分析器被实现为管道功能。在索引文档时,文档中的每个单词都会执行管道函数,搜索时搜索查询中的每个单词都会执行。

对于在管道中工作的函数,它必须实现一个非常简单的接口。它需要接受一个字符串作为输入,它必须以字符串作为输出进行响应。

所以非常简单(和无用)管道函数如下所示:

var simplePipelineFunction = function (word) {
  return word
}

要实际使用此管道功能,我们需要做两件事:

  1. 将其注册为管道功能,这允许lunr正确地序列化和反序列化您的管道。
  2. 将其添加到索引管道。
  3. 这看起来像这样:

    // 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的默认语言是英语,因此,默认情况下,它包含专门用于英语的管道功能。英语和希腊语的不同之处在于您可能会遇到尝试使用英语默认值索引希腊语单词的问题,因此我们需要执行以下操作:

    1. 用我们特定语言的词干分析器替换默认词干分析器
    2. 删除使用非拉丁字符不能很好玩的默认剪裁器
    3. 替换/删除默认的停用词过滤器,它不太可能用于非英语语言。
    4. 修剪器和停用词过滤器实现为管道功能,因此实现特定于语言的过滤器类似于词干分析器。

      所以,要为希腊语设置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中完成,没有任何可配置性。对于大多数语言处理功能而言,这不是一个问题,实际上,大多数人认为单词是较低的。在这种情况下,由于希腊语中词干的复杂性,希腊词干分子只会出现大写单词(我不是希腊语,因此无法评论词汇的复杂程度)。 一个解决方案是在调用希腊词干分析器之前转换为大写,然后在将标记传递给管道的其余部分之前转换回小写。