中文分词自动化探索
在使用Lucene时大家肯能也都碰到了个有趣的现象,用用StandardAnalyzer分词器和QueryParser类直接对查询语句进行解析,得到的结果,如果搜索语句是"搜索引擎",那么转换为Lucene的查询表达式就是"+title:搜 索 引 擎",能搜索到的结果一定是索引文档中“搜索引擎”这四个字连在一起,或者是中间只能包含符号。
比如,搜索表达式是 +title:搜 索 引 擎
那么一下结果将被命中:
这是一个搜索引擎.
google搜索引擎是很不错的工具。
搜索.引擎
而以下的结果将不能被命中:
这是一个提供搜索服务的引擎。
引擎。搜索的引擎
而我们刚开始做搜索引擎实践的时候,开始的时候一般都用过StandardAnalyzer。而后,开始使用词库的中文分词,然后...怎么样就不知道了,呵呵。
而词库分词后的表达式变调了。比如词库里有"搜索""引擎"这两个词,那么解析后的表达式就变为 +title:搜索 引擎,但是,搜索体验也有了质的提升。比如原先,你输入“搜”,就可以搜到带“搜”的所有记录。而现在不一样了,由于“搜索” 成了一个单元,相当于变成了一体了,因此用“搜”一个字肯定是搜不到的。就好象
string index_token = "搜索";
string search_token = "搜";
index_token 和 search_token 肯定是不相等的。
但是用词库的分词,准确性暂且不说,词库的更新,索引就必须跟着改变。这种方式无疑是成本高昂的。那么StandardAnalyzer分词的优点还是有的。是否可以结合这两种分词的优点呢?
假如,建立索引都是按照单字索引。而搜索时按词典分词。那肯定也搜索不出来。但是换个方法,用词典分词器把词分好,比如,“搜索引擎”变成了“搜索 引擎”。然后这样构建表达式:
QueryParser parser = new QueryParser("title", new Lucene.Net.Analysis.Standard.StandardAnalyzer());
BooleanQuery bquery = new BooleanQuery();
Query query1 = parser.Parse(“搜索”);
Query query2 = parser.Parse(“引擎”);
bquery.Add(query1 , BooleanClause.Occur.MUST);
bquery.Add(query2 , BooleanClause.Occur.MUST);
Hits hits = searcher.Search(bquery);
表达式就变成了
+title:搜 索 +title:引 擎
现在又可以搜索到了。
这种方式的优势就很明显了。而这种也是基于词库的,而维护词库的成本也是很高昂的。但是因为现在不用再重建索引,就可以做程序自动在索引和用户输入信息中自动按频率提取分词,而这种词库的变动无疑非常得频繁。但是现在不用重建索引了还怕什么呢?
注:本文内容只经过较小的实验,并未使用过。
by yurow @ http://www.cnblogs.com/birdshover/ 2008年8月3日