浏览 2706 次
锁定老帖子 主题:Lucene针对多语言搜索的一个问题
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2008-02-19
我的一个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); 好生奇怪。 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间: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. |
|
返回顶楼 | |
发表时间:2008-02-20
非常感谢,这正是我需要的。我查了Document和Field类的子类,唯独没查Analyzer的子类...没想到文章就在这个上面。
看来这是Lucene开发者对这种不对称设计的一个补救方案。 |
|
返回顶楼 | |