论坛首页 Java企业应用论坛

Lucene针对多语言搜索的一个问题

浏览 2706 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2008-02-19  
最近在做一个多语言的内容管理系统,搜索引擎部分用的Lucene,本来自信对Lucene还是比较了解的,结果多语言部分还是碰到了麻烦。
我的一个Document数据结构是这样的,一组基本信息,如文章id(articleId),文章创建时间(createTime)等,最后是多语言版本的文章内容(articleContent),针对于不同语言类型,保存Field时名称追加语言识别码,如英文,就是articleContent_en。
Document结构如下:
//Field数量不固定,每种语言都会增加一个Field
Document{
    articleId
    createTime
    ...
    articleContent_en
    articleContent_ch
    ...
}

全文搜索时,只要有一种语言的文章内容匹配,搜索就返回该Document。最后显示的时候,也要给出用户所有语言版本的预览信息。

就在这里,我碰到一个问题,我使用中文Analyzer只能支持中文和英文的索引和搜索,假如文章是日文,Analyzer只能分出其中的中文部分。

开始我不想改变数据结构,毕竟这个结构对于搜索来说最简单,那么,我想到的是对不同语言的文章内容使用不同的Analyzer进行分词,也就是当我判断文章内容是日文的时候,使用Lucene自带的StandardAnalyzer进行一元分词处理。但很快发现这个方案行不通,因为Lucene在构建索引时,Analyzer是Document级的,也就是一个Document的所有Field只能使用同一个Analyzer进行解析,Lucene的示意代码如下:
//Field中没有传入Analyzer的方法
Document.add(new Field(...));

//此处可以看出,Analyzer是和Document级别对应的
IndexWriter.addDocument(Document, Analyzer);


之后我又想到了第二个解决方案,修改我的Document结构,将一个Document分解为基本信息Document和单个语言文章内容Document这样几个Document的组合结构。每个Document都有articleId这个Field,增加一个docType的Field区分是基本信息的Document还是文章内容的Document,假设基本信息的docType为1,文章内容为2。
Document结构如下:
//基本信息Document
Document{
    docType = 1
    articleId
    createTime
    ...
}

//文章内容Document
Document{
    docType = 2
    articleId
    articleContent
}

这样对于不同的语言种类的同一篇文章,就可以使用不同的Analyzer进行索引了。但是很快发现如果这么拆分,复合搜索的过程会变得很复杂,比如以下条件:
文章关键字为“尼斯湖 水怪 考证”
文章创建时间要在2005年之后


搜索过程变成了:
1. 用关键字和docType等于2两个条件搜索进行联合搜索,得出搜索含有关键字的文章Document。
2. 从第一次搜索结果的Document中提取所有关键字匹配的文章的articleId,联合createTime早于2005年以及docType等于1这两个条件进行第二次搜索,得出真正符合用户要求的结果。
3. 进行当前分页页面的内容提取,将基本信息Document作为主信息,利用articleId和docType等于2两个条件搜索其下所有语言版本文章内容,组合成完整信息返回给页面。代码如下:
class Article{
    Document articleBaseInfoDoc;
    List articleContentList;
}


这个方案理论上能解决问题,但是会使搜索过程复杂很多,也不是我希望看到的。

于是想到第三种方案,修改Analyzer。把我使用的中文Analyzer进行修改,判断语言种类,如果不是中文,则直接按照StandartAnalyzer方式进行分词。但是我用的那个Analyzer不是开源的,源码经过了混淆,读起来都异常费劲,更别说修改。

不知道有没有人碰到过和我相同的问题,能给我一些提示,非常感谢。

另外:
通过这个事我发现了Lucene设计上的一个费解的事情,Lucene索引时不能对Field级别进行不同Analyzer分词处理,但是搜索的时候可以进行不同Field使用不同Analyzer分词搜索,搜索代码如下:
//针对每一个Field的搜索解析器都可以传入不同的Analyzer
QueryParser parser = new QueryParser("articleContent", analyzer);

好生奇怪。
   发表时间:2008-02-19  
针对每一个field(articleContent_*)使用不同的分词器
* <pre>
*   PerFieldAnalyzerWrapper aWrapper =
*      new PerFieldAnalyzerWrapper(new StandardAnalyzer());
*   aWrapper.addAnalyzer("firstname", new KeywordAnalyzer());
*   aWrapper.addAnalyzer("lastname", new KeywordAnalyzer());
* </pre>

In this example, StandardAnalyzer will be used for all fields except "firstname"
and "lastname", for which KeywordAnalyzer will be used.
0 请登录后投票
   发表时间:2008-02-20  
非常感谢,这正是我需要的。我查了Document和Field类的子类,唯独没查Analyzer的子类...没想到文章就在这个上面。

看来这是Lucene开发者对这种不对称设计的一个补救方案。
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics