LUCENE 1.X 与 2.X 版本 在 Field 对象构建及 QueryParser 对象使用方面的区别
我们在学习LUCENE时,经常会遇到这样的情况:在网上搜索到的或书上的一些例程在调试时会产生编译错误,这是因为LUCENE2.0版本在Field(域)对象的构建及QueryParser对象的使用方面相对于1.X版本发生了一些变化,下面我们分别从LUCENE域类型、1.X与2.X版本各自对Field(域)对象的构建及QueryParser的具体使用方法讨论这个问题。
1、 LUCENE提供的四种不同类型的Field(域)
(1)
Keyword域—— 不需要被分析,但是会逐字被索引并被存储,该类型适用于原始值,即需要将内容全部保留的域。如果你了解分析器,你就会明白,当域内容被分析器分析,它的原始内容就有可能被或多或少改变,比如将使用频繁但没有实际意义的词去掉(类似 an in on the等)、将语汇统一改为小写等。虽然分析器这样做可以为我们提供更高质量的搜索,但有的时候我们并不希望分析器对我们原始域的内容进行任何改变,例如姓名、URL、街道地址等。这时候我们就可以把域定义为Keyword域
(2)
UnIndexed 域— 即不需要被分析,也不进行索引,但该值同样被存储于索引文件中,当域内容不会被做为搜索关键字,但又需要做为搜索结果显示出来时,用UnIndexed 域类型是最好的选择。
(3)
UnStored 域— 同UnIndexed 域刚好相反,这种类型的域需要被分析与索引,但并不存储在索引文件中,该类型适用于那些不需要以原始形式进行检索的大数据量文本,如网页正文或其它类型的文本文档等。
(4)
Text 域——— 需要被分析且索引,若被索引的数据是字符串,则同时被存储在索引文件中;若被索引的数据来自Reader对象,则不会被存储在索引文件中。
2、 1.X版本与2.X版本在构建Field(域)对象及使用QueryParser的具体方式比较
(1) Field 对象构建的区别
LUCENE 1.X 版本的Field对象分别有 Keyword、UnIndexed、UnStored、Text等静态方法,这些方法通过传入相应的参数,可构建相应类型的域,并将内容添加到域中。而LUCENE2.X版本的Field对象的内部类Field.Store与Field.Index的静态属性来表示被分析、索引及存储的情况,两者对不同域类型、特性及使用举例如下表:
域方法/类型(1.X)
|
域方法/类型(2.X)
|
特性
|
Field.Keyword(String,String)
|
New Field(String,String, Field.Store.YES, Field.Index.UN_TOKENIZED
|
被索引
被存储
|
Field.UnIndexed(String,String)
|
New Field(String,String,Field.Store.YES, Field.Index.NO)
|
被存储
|
Field.UnStored(String,String)
|
New Field(String,String,Field.Store.NO, Field.Index.TOKENIZED)
|
被分析
被索引
|
Field.Text(String,String)
|
New Field(String,String,Field.Store.YES, Field.Index.TOKENIZED)
|
被分析
被索引
被存储
|
Field.Text(String,Reader)
|
New Field(String,String,Field.Store.NO, Field.Index.TOKENIZED)
|
被分析
被索引
|
(2) QueryParser 对象使用的区别
LUCENE 1.X版本采用QueryParser的静态方法parse直接产生Query对象,使用时只需将关键字,域名称及分析器对象一次性传入即可,类似于以下用法:
Query query = QueryParser.parse(keyword, "contents", new StandardAnalyzer ());
而LUCENE 2.X版本中QueryParser对象中的parse方法变为非静态方法,需要显示创建QueryParser对象,然后调用其parse(String keyword)方法:
QueryParser parser = new QueryParser("contents", new StandardAnalyzer ());
Query query = parser.parse(keyword);
3、源代码示例:
1.X版本:
package searchtest;
import org.apache.lucene.store.*;
import org.apache.lucene.document.*;
import org.apache.lucene.analysis.*;
import org.apache.lucene.index.*;
import org.apache.lucene.search.*;
import org.apache.lucene.queryParser.*;
class SearchTest
{
public static void main(String[] args){
try{
//在内存中建立索引
Directory directory = new RAMDirectory();
//生成分析器对象,用于分词等
Analyzer analyzer = new SimpleAnalyzer();
//索引书写器
IndexWriter writer = new IndexWriter(directory,analyzer,true);
//将要建立索引的字符串
String[] docs =
{
"中 国 人 d e",
"a b c d e a b c d e",
"a b c d e f g h i j",
"a c e",
"e c a",
"中 国 人 a c e",
"中 国 人 a b c"
};
//将要建立索引的字符串添加到索引中
for (int j=0;j<docs.length ;j++ )
{
Document d = new Document();
d.add(Field.Text("contents",docs[j]));
writer.addDocument(d);
}
writer.close();
//生成搜过对象
Searcher searcher = new IndexSearcher(directory);
//对于查询的字符串
String[] queries = {"/"中 国 人/""};
//生成结果集对象,初始化为空值
Hits hits = null;
//生成QueryParser对象
//依次使用查询字符串生成查询对象Query
for(int j=0;j<queries.length;j++){
Query query = QueryParser.parse(queries[j],"contents",analyzer);
//输出要查询的内容
System.out.println("Query:" + query.toString("contents"));
//返回结果集
hits = searcher.search(query);
//输出搜索到的总文档数
System.out.println(hits.length() + " total results");
//依次输出搜索到的文档内容
for (int i = 0;i<hits.length() && i<10 ;i++ )
{
Document d = hits.doc(i);
System.out.print(i + " " + hits.score(i))
System.out.println(" " + d.get("contents"));
}
searcher.close();
}
}catch (Exception e){
e.printStackTrace();
}
}
}
2.X版本:
package searchtest;
import org.apache.lucene.store.*;
import org.apache.lucene.document.*;
import org.apache.lucene.analysis.*;
import org.apache.lucene.index.*;
import org.apache.lucene.search.*;
import org.apache.lucene.queryParser.*;
class SearchTest
{
public static void main(String[] args){
try{
//在内存中建立索引
Directory directory = new RAMDirectory();
//生成分析器对象,用于分词等
Analyzer analyzer = new SimpleAnalyzer();
//索引书写器
IndexWriter writer = new IndexWriter(directory,analyzer,true);
//将要建立索引的字符串
String[] docs =
{
"中 国 人 d e",
"a b c d e a b c d e",
"a b c d e f g h i j",
"a c e",
"e c a",
"中 国 人 a c e",
"中 国 人 a b c"
};
//将要建立索引的字符串添加到索引中
for (int j=0;j<docs.length ;j++ )
{
Document d = new Document();
d.add(new Field("contents", docs[j], Field.Store.YES, Field.Index.TOKENIZED));
writer.addDocument(d);
}
writer.close();
//生成搜过对象
Searcher searcher = new IndexSearcher(directory);
//对于查询的字符串
String[] queries = {"/"中 国 人/""};
//生成结果集对象,初始化为空值
Hits hits = null;
//生成QueryParser对象
QueryParser parser = new QueryParser("contents",analyzer);
//依次使用查询字符串生成查询对象Query
for(int j=0;j<queries.length;j++){
Query query = parser.parse(queries[j]);
//输出要查询的内容
System.out.println("Query:" + query.toString("contents"));
//返回结果集
hits = searcher.search(query);
//输出搜索到的总文档数
System.out.println(hits.length() + " total results");
//依次输出搜索到的文档内容
for (int i = 0;i<hits.length() && i<10 ;i++ )
{
Document d = hits.doc(i);
System.out.print(i + " " + hits.score(i))
System.out.println(" " + d.get("contents"));
}
searcher.close();
}
}catch (Exception e){
e.printStackTrace();
}
}
}