目录[-]
1. 概述
2. lucene 的包结构
3. 索引文件格式
4. lucene中主要的类
4.1. Document文档类
4.1.1.常用方法
4.1.2.示例
4.2. Field字段类
4.2.1.构造方法
4.2.2.Store类
4.2.3.Index类
4.2.4.示例
4.3. IndexWriter类
4.3.1.构造方法
4.3.2.添加文档
4.3.3.性能参数
4.3.4.限制Field的长度
4.3.5.复合索引格式
4.3.6.优化索引
4.3.7.示例
4.4. Directory类
4.5. IndexReader类
4.5.1.删除文档
4.5.2.反删除
4.5.3.按字段删除
4.5.4.示例
4.6. IndexModifier类
4.6.1.示例
4.7. IndexSearcher类
4.7.1.构造方法
4.7.2.search方法
4.7.3.Searcher的explain方法
4.7.4.示例
4.8. Hits类
4.8.1.概述
4.8.2.常用方法
4.8.3.示例
4.9. QueryParser类
4.9.1.改变默认的布尔逻辑
4.9.2.不需要分词
4.9.3.设置坡度值,支持FuzzyQuery
4.9.4.设置通配符,支持WildcardQuery
4.9.5.查找指定的Field
4.9.7.现在还不支持SpanQuery
4.10. MultiFieldQueryParser类--多域搜索
4.11. MultiSearcher类--多个索引搜索
4.12. ParalellMultiSearcher类---多线程搜索
5. 排序
5.1. Sort类
5.2. SortField类
5.3. 指定排序的法则
5.3.1.按照文档的得分降序排序
5.3.2.按文档的内部ID升序排序
5.3.3.按照一个Field来排序
5.3.4.按照多个Field来排序
5.3.5.改变SortField中的Locale信息
6. 过滤器
7. 分析器Analysis
7.1. 自带分析器和过滤器
7.2. 第三方过分析器
7.2.1.JE分词用法
7.2.1.1. 示例
7.2.1.2. 设定正向最大匹配的字数
7.2.1.3. 添加新词
8. 索引的合并
9. 各种Query
9.1. 概述
9.2. 使用特定的分析器搜索
9.3. 按词条搜索—TermQuery
9.4. 按“与或”搜索—BooleanQuery
9.5. 在某一范围内搜索—RangeQuery
9.6. 使用前缀搜索—PrefixQuery
9.7. 短语搜索—PhraseQuery
9.8. 多短语搜索—MultiPhraseQuery
9.9. 模糊搜索—FuzzyQuery
9.10. 通配符搜索—WildcardQuery
9.11. 跨度搜索
9.11.1. SpanTermQuery
9.11.2. SpanFirstQuery
9.11.3. SpanNearQuery
9.11.4. SpanOrQuery
9.11.5. SpanNotQuery
9.12. RegexQuery—正则表达式的查询
10. 评分机制
10.1. 概述
11. Lucene的索引“锁”
Lucene是一个全文检索引擎的架构,提供了完整的查询引擎和索引引擎。Lucene以其方便使用、快速实施以及灵活性受到广泛的关注。它可以方便地嵌入到各种应用中实现针对应用的全文索引、检索功能,本总结使用lucene--2.3.2。
1、org.apache.lucene.analysis对需要建立索引的文本进行分词、过滤等操作, 语言分析器,主要用于的切词Analyzer是一个抽象类,管理对文本内容的切分词规则。
2、org.apache.lucene.analysis.standard是标准分析器
3、org.apache.lucene.document提供对Document和Field的各种操作的支持。索引存储时的文档结构管理,类似于关系型数据库的表结构。Document相对于关系型数据库的记录对象,Field主要负责字段的管理。
4、org.apache.lucene.index是最重要的包,用于向Lucene提供建立索引时各种操作的支持。索引管理,包括索引建立、删除等。索引包是整个系统核心,全文检索的根本就是为每个切出来的词建索引,查询时就只需要遍历索引,而不需要去正文中遍历,从而极大的提高检索效率。
5、org.apache.lucene.queryParser提供检索时的分析支持。查询分析器,实现查询关键词间的运算,如与、或、非等。
6、org.apache.lucene.search 负责检索。检索管理,根据查询条件,检索得到结果。
7、org.apache.lucene.store提供对索引存储的支持。数据存储管理,主要包括一些底层的I/0操作。
8、org.apache.lucene.util提供一些常用工具类和常量类的支持
a) .fnm格式 包含了Document中所有field名称
b) .fdt与.fdx格式 .fdt文件用于存储具有Store.YES属性的Field的数据;.fdx是一个索引,用于存储Document在.fdt中的位置。
c) .tis 与.tii格式 .tis文件用于存储分词后的词条(Term),而.tii就是它的索引文件,它表明了每个.tis文件中的词条的位置。
d) deletable格式 文档被删除后,会首先在deletable文件中留下一个记录,要真正删除时,才将索引除去。
e) 复合索引格式 .cfs
使用IndexWriter的useCompoundFile() 默认为True
方法 |
描述 |
void add(Field field) |
往Document对象中添加字段 |
void removeField(String name) |
删除字段。若多个字段以同一个字段名存在,则删除首先添加的字段;若不存在,则Document保持不变 |
void removeFields(String name) |
删除所有字段。若字段不存在,则Document保持不变 |
Field getField(String name) |
若多个字段以同一个字段名存在,则返回首先添加的字段;若字段不存在,则Document保持不变 |
Enumeration fields() |
返回Document对象的所有字段,以枚举类型返回 |
Field [] getFields(String name) |
根据名称得到一个Field的数组 |
String [] getValues(String name) |
根据名称得到一个Field的值的数组 |
Document doc1 = new Document();
doc1.add(new Field("name", "word1 word2 word3",
Field.Store.NO,Field.Index.TOKENIZED));
Document doc2 = new Document();
doc2.add(new Field("name", "word1 word2 word3",
Field.Store.NO,Field.Index.TOKENIZED));
1) public Field(String name,String value,Store store,Index index);//直接的字符串方式
2) public Field(String name,String value,Store store,Index index,TermVector termVector);
3) public Field(String name,String value,Reader reader);//使用Reader从外部传入
4) public Field(String name,String value,Reader reader,TermVector termVector);
5) public Field(String name,byte[] value,Store store)//使用直接的二进制byte传入
当Field值为二进制时,可以使用Lucene的压缩功能将其值进行压缩。
静态属性 |
描述 |
Store.NO |
表示该Field不需要存储 |
Store.YES |
表示该Field需要存储 |
Store.COMPRESS |
表示用压缩方式来保存这个Field的值 |
静态属性 |
描述 |
Index.NO |
不需要索引 |
Index.TOKENIZED |
先被分词再被索引 |
Index.UN_TOKENIZED |
不对该Field进行分词,但会对它进行索引 |
Index.NO_NORMS |
对该Field进行索引,但是不使用Analyzer,同时禁止它参加评分,主要是为了减少内存的消耗。 |
new Field("name", "word1 word2 word3",Field.Store.YES,Field.Index.TOKENIZED)
1) public IndexWriter(String path,Analyzer a,Boolean create)
2) public IndexWriter(File path,Analyzer a,Boolean create)
3) public IndexWriter(Directory d,Analyzer a,Boolean create)
第一个参数:索引存放在什么地方
第二个参数:分析器,继承自org.apache.lucene.analysis.Analyzer类
第三个参数:为true时,IndexWriter不管目录内是否已经有索引了,一律清空,重新建立;当为false时,则IndexWriter会在原有基础上增量添加索引。所以在更新的过程中,需要设置该值为false。
public void addDocument(Document doc)
public void addDocument(Document doc,Analyzer analyzer)//使用一个开发者自定义的,而非事先在构建IndexWriter时声明的Analyzer来进行分析
writer.addDocument(doc1);
1) mergeFactor控制Lucene在把索引从内存写入磁盘上的文件系统时内存中最大的Document数量,同时它还控制内存中最大的Segment数量。默认为10.
writer.setMergeFactor(10);
2) maxMergeDocs限制一个Segment中最大的文档数量。一个较大的maxMergeDocs适用于对大批量的文档建立索引,增量式的索引则应使用较小的maxMergeDocs。
writer.setMaxMergeDocs(1000);
3) minMergeDocs用于控制内存中持有的文档数量的,它对磁盘上的Segment大小没有任何影响。
maxFieldLength限制Field的长度,默认值为10000.最大值100000个。
public void setMaxFieldLength(int maxFieldLength)
writer.addDocument(doc1);
writer.setMaxFieldLength(100000);
writer.addDocument(doc2);
setUseCompoundFile(Boolean) 默认true
writer.setUseCompoundFile(true);//复合索引
writer.setUseCompoundFile(false);
writer.optimize();
将磁盘上的多个segment进行合并,组成一个全新的segment。这种方法并不会增加建索时的速度,反而会降低建索的速度。所以应该在建完索引后在调用这个函数
IndexWriter writer = new IndexWriter(path, new StandardAnalyzer(), true);
writer.addDocument(doc1);
writer.addDocument(doc2);
Sytem.out.println(writer.docCount());
writer.close();
IndexSearcher searcher = new IndexSearcher(path);
Hits hits = null;
Query query = null;
QueryParser parser =new QueryParser("name", new StandardAnalyzer());
query =parser.parse("word1");
hits = searcher.search(query);
System.out.println("查找 word1 共" + hits.length() + "个结果");
Directory:用于索引的存放位置
a) FSDirectory.getDirectory(path, true)第二个参数表示删除掉目录内原有内容
IndexWriter writer = new IndexWriter(FSDirectory.getDirectory(path, true), new StandardAnalyzer(), true);//删除原有索引
或
FSDirectory fsDir=FSDirectory.getDirectory(path,true);
IndexWriter writer = new IndexWriter(fsDir, new StandardAnalyzer(), true);
b) RAMDirectory在内存中存放,读取速度快,但程序一运行结束,它的内容就不存在了
RAMDirectory ramDir=new RAMDirectory();
IndexWriter writer = new IndexWriter(ramDir, new StandardAnalyzer(), true);
或
IndexWriter writer = new IndexWriter(new RAMDirectory(), new StandardAnalyzer(), true);
IndexReader类――索引的读取工具
IndexReader reader=IndexReader.open(path);
reader.deleteDocument(0);//删除第一个
reader.close();
reader.undeleteAll();
reader.deleteDocuments(new Term("name","word1"));
若要真正物理删除,则只需使用IndexWriter对索引optimize一次即可!
IndexReader reader=IndexReader.open(path);
for(int i=0;i<reader.numDocs();i++){
System.out.println(reader.document(i));
}
System.out.println("版本:"+reader.getVersion());
System.out.println("索引内的文档数量:"+reader.numDocs());
//reader.deleteDocuments(new Term("name","word1"));
Term term1=new Term("name","word1");
TermDocs docs=reader.termDocs(term1);
while(docs.next())
{
System.out.println("含有所查找的"+term1+"的Document的编号为"+docs.doc());
System.out.println("Term在文档中的出现次数"+docs.freq());
}
reader.close();
集成了IndexWriter的大部分功能和IndexReader中对索引删除的功能 ------ Lucene2.0的新类
public static void main(String[] args) throws Exception {
IndexModifier modifier=new IndexModifier("C:\\Q1",new StandardAnalyzer(),true);
Document doc1=new Document();
doc1.add(new Field("bookname","钢铁是怎样炼成的",Field.Store.YES,Field.Index.TOKENIZED));
Document doc2=new Document();
doc2.add(new Field("bookname","山山水水",Field.Store.YES,Field.Index.TOKENIZED));
modifier.addDocument(doc1);
modifier.addDocument(doc2);
System.out.println(modifier.docCount());
modifier.setUseCompoundFile(false);
modifier.close();
IndexModifier mo=new IndexModifier("C:\\Q1",new StandardAnalyzer(),false);
mo.deleteDocument(0);
System.out.println(mo.docCount());
mo.close();
}
IndexSearcher searcher = new IndexSearcher(String path);
IndexSearcher searcher = new IndexSearcher(Directory directory);
IndexSearcher searcher = new IndexSearcher(IndexReader r);
IndexSearcher searcher = new IndexSearcher(IndexReader r,Boolean closeReader);
IndexSearcher searcher = new IndexSearcher(path);
IndexSearcher searcher = new IndexSearcher(FSDirectory.getDirectory(path,false) );
//返回Hits对象
public Hits search(Query query)
public Hits search(Query query,Filter filter)
public Hits search(Query query,Sort sort)
public Hits search(Query query,Filter filter,Sort sort)
//检索只返回得分最高的Document
public TopDocs search(Query query,Filter filter,int n)
public TopDocs search(Weight weight,Filter filter,int n)
public TopFieldDocs search(Weight weight,Filter filter,int n,Sort sort)
public TopFieldDocs search(Query query,Filter filter,int n,Sort sort)
//传入HitCollector,将结果保存在HitCollector中
public void search(Query query,HitCollector results)
public void search(Query query,Filter filter,HitCollector results)
public void search(Weight weight,Filter filter,HitCollector results)
public Explaination explain(Query query,int doc)throws IOException
for(int i=0;i<hits.length()&&i<10;i++)
{
Document d=hits.doc(i);
System.out.println(i+" "+hits.score(i)+" "+d.get("contents"));
System.out.println(searcher.explain(query,hits.id(i)).toString());
}
IndexSearcher searcher = new IndexSearcher(path);
Hits hits = null;
Query query = null;
QueryParser parser =new QueryParser("contents", new StandardAnalyzer());
query =parser.parse("11");
hits = searcher.search(query);
System.out.println("查找 word1 共" + hits.length() + "个结果");
for(int i=0;i<hits.length()&&i<10;i++)
{
Document d=hits.doc(i);
System.out.println(d+" "+i+" "+hits.score(i)+" "+d.get("contents"));
}
searcher.close();
Hits类――检索结果
方法名 |
描述 |
int length() |
返回搜索到结果的总数量 |
Document doc(int i) |
返回第i个文档 |
int id(int i) |
返回第i个文档的内部ID号 |
float score(int i) |
返回第i个文档的得分 |
Iterator iterator() |
取得Hits集合的遍历对象 |
for(int i=0;i<hits.length()&&i<10;i++)
{
Document d=hits.doc(i);
System.out.println(d+" "+" "+hits.score(i)+" "+d.get("contents"));
System.out.println("文档的内部ID号:" + hits.id(i));
}
Ø 默认为“或”关系
Query query = null;
QueryParser parser =new QueryParser("contents", new StandardAnalyzer());
query =parser.parse("hello world!");
System.out.println(query.toString());
Ø 改变默认布尔逻辑
Query query = null;
QueryParser parser =new QueryParser("contents", new StandardAnalyzer());
parser.setDefaultOperator(QueryParser.AND_OPERATOR);
query =parser.parse("hello world");//若world后加!会出错
System.out.println(query.toString());
Ø AND OR NOT – 关键字
也可以不用改变默认布尔逻辑,而直接让用户在输入关键字时指定不同词条间的布尔联系。例如,用户输入 hello AND world 必须为大写
逻辑与:AND (大写)
逻辑或:OR (大写)
逻辑非:- 例如: hello - world
也可以是NOT 例如: hello NOT world
不进行分词,将其完整的作为一个词条进行处理,则需要在词组的外面加上引号
String queryStr="\"God helps those who help themselves\"";
QueryParser parser = new QueryParser("bookname",new StandardAnalyzer());
parser.setDefaultOperator(QueryParser.AND_OPERATOR);
Query query=parser.parse(queryStr);
System.out.println(query.toString());
String queryStr="\"God helps those who help themselves\"~1";//设置坡度为1
QueryParser parser = new QueryParser("bookname",new StandardAnalyzer());
Query query=parser.parse(queryStr);
System.out.println(query.toString());
String queryStr="wor?"
QueryParser parser = new QueryParser("bookname",new StandardAnalyzer());
parser.setDefaultOperator(QueryParser.AND_OPERATOR);
Query query=parser.parse(queryStr);
System.out.println(query.toString());
String queryStr="linux publishdate:2006-09-01";
QueryParser parser = new QueryParser("bookname",new StandardAnalyzer());
parser.setDefaultOperator(QueryParser.AND_OPERATOR);
Query query=parser.parse(queryStr);
System.out.println(query.toString());
例如:要求用户选择某一方面的
QueryParser parser=new QueryParser("publishdate",
new StandardAnalyzer());
Query query=parser.parse(queryStr);
System.out.println(query.toString());
输出结果为publishdate:[081xmghs0 TO 0boeetj3z]
因为建立索引时,如果按照日期表示的字符串来进行索引,实际上比较的是字符串的字典顺序。而首先将日期转为以毫秒计算的时间后,则可以精确地比较两个日期的大小了。于是,lucene提供DateTools工具,用来完成其内部对时间的转化和处理,将毫秒级的时间转化为一个长字符串来进行表示,并进行索引。所以,遇到日期型数据时,最好用DateTools进行转换,再进行索引!
//在不同的Field上进行不同的查找
public static Query parse(String []queries,String[] fields,Analyzer analyzer)throws ParseException
//在不同的Field上进行同一个查找,指定它们之间的布尔关系
public static Query parse(String query,String[] fields,BooleanClause.Occur[] flags,Analyzer analyzer) throws ParseException
//在不同的Field上进行不同的查找,指定它们之间的布尔关系
public static Query parse(String []queries,String [] fields,BooleanClause.Occur[] flags,Analyzer analyzer)throws ParseException
String [] queries={"钢", "[10 TO 20]"};
String[] fields={“bookname”,”price”};
BooleanClause.Occur[] clauses={BooleanClause.Occur.MUST,BooleanClause.Occur.MUST};
Query query=MultiFieldQueryParser.parse(queries,fields,clauses,new StandardAnalyzer());
System.out.println(query.toString());
IndexSearcher searcher1=new IndexSearcher(path1);
IndexSearcher searcher2=new IndexSearcher(path2);
IndexSeacher [] searchers={searcher1,seacher2};
MultiSearcher searcher=new MultiSearcher(searchers);
Hits hits=searcher.search(query);
for(int i=0;i<hits.length();i++){
System.out.println(hits.doc(i));
}
IndexSearcher searcher1=new IndexSearcher(path1);
IndexSearcher searcher2=new IndexSearcher(path2);
IndexSearcher [] searchers={searcher1,searcher2};
ParallelMultiSearcher searcher=new ParallelMultiSearcher(searchers);
long start=System.currentTimeMillis();
Hits hits=searcher.search(query);
long end=System.currentTimeMillis();
System.out.println((end-start)+"ms");
public Sort()
public Sort(String field)
public Sort(String field,Boolean reverse) //默认为false,降序排序
public Sort(String[] fields)
public Sort(SortField field)
public Sort(SortField[] fields)
Sort sort=new Sort(“bookname”);按照“bookname“这个Field值进行降序排序
Sort sort=new Sort(“bookname”,true) //升序排序
Sort sort=new Sort(new String[]{“bookNumber”,”bookname”,”publishdate”});按照三个Field进行排序,但无法指定升序排序,所以用SortField
public SortField(String field)
public SortField(String field,Boolean reverse)
public SortField(String field,int type) //type表示当前Field值的类型
public SortField(String field,int type,boolean reverse) //默认为false,升序
Field值的类型:SortField.STRING、SortField.INT、SortField.FLOAT
SortField sf1=new SortField(“bookNumber”,SortField.INT,false);
SortField sf2=new SortField(“bookname”,SortField.STRING,false);
Hits hits=searcher.search(query,Sort.RELEVANCE);
Hits hits=searcher.search(query, Sort.INDEXORDER);
Sort sort=new Sort();
SortField sf=new SortField(“bookNumber”,SortField.INT,false);
sort.setSort(sf);
Hits hits=searcher.search(query,sort);
Sort sort=new Sort();
SortField sf1=new SortField(“bookNumber”,SortField.INT,false);//升序
SortField sf2=new SortField(“publishdate”,SortField.STRING,true);//降序
sort.setSort(new SortField[]{sf1,sf2});
Hits hits=searcher.search(query,sort);
String str1=”我”; String str2=”你”;
Collator co1=Collator.getInstance(Locale.CHINA);
Collator co2=Collator.getInstance(Locale.JAPAN);
System.out.println(Locale.CHINA+”:”+co1.compare(str1,str2));
System.out.println(Locale.JAPAN+”:”+co2.compare(str1,str2));
输出结果为:
zh_CN:1
ja_JP:-1
所以
public SortField(String field,Locale locale)
public SortField(String field,Locale locale,boolean reverse)
使用public Hits search(Query query,Filter filter)
(1)简单过滤
Hits hits=searcher.search(query,new AdvancedSecurityFilter());//过滤掉securitylevel为0的结果
(2)范围过滤—RangeFilter
只显示中间的
RangeFilter filter=new RangeFilter(“publishdate”,”1970-01-01”,”1998-12-31”,true,true”);
Hits hits=searcher.search(query,filter);
无上边界
public static RangeFilter More(String fieldname,String lowerTerm)
无下边界
public static RangeFilter Less(String fieldname,String upperTerm)
(3)在结果中查询QueryFilter
RangeQuery q=new RangeQuery(new Term(“publicshdate”,”1970-01-01”),
new Term(“publishdate”,”1999-01-01”),true);
QueryFilter filter=new QueryFilter(q);
Hits hits=searcher.search(query,filter);
Ø 标准过滤器:StandardAnalyzer
Ø 大小写转换器:LowerCaseFilter
Ø 忽略词过滤器:StopFilter
public StopFilter(TokenStream input,String [] stopWords)
public StopFilter(TokenStream in,String [] stopWords,boolean ignoreCase)
public StopFilter(TokenStream input,Set stopWords,boolean ignoreCase)
public StopFilter(TokenStream in, Set stopWords)
其中,参数TokenStream代表当前正在进行处理的流;String类型的数组代表一个用数组表示的忽略词集合;Set类型的参数与String一样,是用来表示忽略词集合的;boolean表示当与忽略词集合中的词进行匹配时,是否需要忽略大小写。
Ø 长度过滤器:LengthFilter
Ø PerFieldAnalyzerWrapper
Ø WhitespaceAnalyzer
String str="str1 str2 str3";
StringReader reader=new StringReader(str);
Analyzer anlyzer=new WhitespaceAnalyzer();
TokenStream ts=anlyzer.tokenStream("", reader);
Token t=null;
while( (t=ts.next())!=null ){
System.out.println(t.termText());
}
Ø 单字分词
Ø 二分法:CJKAnalyzer、中科院ICTCLAS分词、JE分词
Ø 词典分词
import jeasy.analysis.MMAnalyzer;
IndexWriter writer = new IndexWriter(INDEX_STORE_PATH, new MMAnalyzer()
, true);
String str=" Lucene是一个全文检索引擎的架构,"+
"提供了完整的查询引擎和索引引擎。Lucene以其方便使用、快" +
"速实施以及灵活性受到广泛的关注。它可以方便地嵌入到各种应用" +
"中实现针对应用的全文索引、检索功能,本总结使用lucene--2.3.2。";
MMAnalyzer analyzer=new MMAnalyzer();
try{
System.out.println(analyzer.segment(str, "|"));
}
catch(Exception e)
{
e.printStackTrace();
}
输出结果:lucene|一个|全文|检索|引擎|架构|提供|完整|查询|。。。。
MMAnalyzer analyzer=new MMAnalyzer(4);
MMAnalyzer.addWord(String word);
MMAnalyzer.addDictionary(Reader reader);
MMAnalyzer analyzer=new MMAnalyzer();
MMAnalyzer.addWord("迈克尔雷第");
RAMDirectory RAMDir=new RAMDirectory();
IndexWriter writer = new IndexWriter(RAMDir, new StandardAnalyzer(), true);//删除原有索引
IndexWriter writer2=new IndexWriter(FSDirectory.getDirectory(path,true),
new StandardAnalyzer(), true);
writer.addDocument(doc1);
writer2.addDocument(doc2);
writer.close();
writer2.addIndexes(new Directory[]{RAMDir});
writer2.close();
注意:在合并前一定要先关闭要加的索引器。
query.toString()查看原子查询
IndexSearcher searcher = new IndexSearcher(path );
Hits hits = null;
Query query = null;
QueryParser parser =new QueryParser("contents", new StandardAnalyzer());
query =parser.parse("11 aand hello");
hits=searcher.search(query); //查找 name:11 name:hello 共1个结果
System.out.println("查找 "+query.toString()+" 共" + hits.length() + "个结果");
Query query = null;
query=new TermQuery(new Term("name","word1 aand"));
hits=searcher.search(query);// 查找 name:word1 aand 共0个结果
System.out.println("查找 "+query.toString()+" 共" + hits.length() + "个结果");
1.和: MUST与MUST_NOT
2.或: SHOULD与SHOULD
3.A与B的并集-B MUST与MUST_NOT
Query query1=null;
Query query2=null;
BooleanQuery query=null;
query1=new TermQuery(new Term("name","word1"));
query2=new TermQuery(new Term("name","word2"));
query=new BooleanQuery();
query.add(query1,BooleanClause.Occur.MUST);
query.add(query2,BooleanClause.Occur.MUST_NOT);
Term beginTime=new Term("time","200001");
Term endTime=new Term("time","200005");
RangeQuery query=null;
query=new RangeQuery(beginTime,endTime,false);//不包含边界值
Term pre1=new Term("name","wor");
PrefixQuery query=null;
query = new PrefixQuery(pre1);
a)默认坡度为0
PhraseQuery query = new PhraseQuery();
query.add(new Term(“bookname”,”钢”));
query.add(new Term(“bookname”,”铁”));
Hits hits=searcher.search(query); //搜索“钢铁”短语,而非“钢”和“铁”
b)设置坡度,默认为0
PhraseQuery query = new PhraseQuery();
query.add(new Term(“bookname”,”钢”));
query.add(new Term(“bookname”,”铁”));
query.setSlop(1);
Hits hits=searcher.search(query);//搜索“钢铁”或“钢*铁”中含一字
a)
MultiPhraseQuery query=new MultiPhraseQuery();
//首先向其中加入要查找的短语的前缀
query.add(new Term(“bookname”,”钢”));
//构建3个Term,作为短语的后缀
Term t1=new Term(“bookname”,”铁”);
Term t2=new Term(“bookname”,”和”);
Term t3=new Term(“bookname”,”要”);
//再向query中加入所有的后缀,与前缀一起,它们将组成3个短语
query.add(new Term[]{t1,t2,t3});
Hits hits=searcher.search(query);
for(int i=0;i<hits.length();i++)
System.out.println(hits.doc(i));
b)
MultiPhraseQuery query=new MultiPhraseQuery();
Term t1=new Term(“bookname”,”钢”);
Term t2 = new Term(“bookname”,”和”);
query.add(new Term[]{t1,t2});
query.add(new Term(“bookname”,”铁”));
c)
MultiPhraseQuery query=new MultiPhraseQuery();
Term t1=new Term(“bookname”,”钢”);
Term t2 = new Term(“bookname”,”和”);
query.add(new Term[]{t1,t2});
query.add(new Term(“bookname”,”铁”));
Term t3=new Term(“bookname”,”是”);
Term t4=new Term(“bookname”,”战”);
query.add(new Term[]{t3,t4});
使用的算法为levenshtein算法,在比较两个字符串时,将动作分为3种:
l 加一个字母
l 删一个字母
l 改变一个字母
FuzzyQuery query=new FuzzyQuery(new Term(“content”,”work”));
public FuzzyQuery(Term term)
public FuzzyQuery(Term term,float minimumSimilarity)throws IllegalArgumentException
public FuzzyQuery(Term term,float minimumSimilarity,int prefixLength)throws IllegalArgumentException
其中minimumSimilarity为最小相似度,越小则文档的数量越多。默认为0.5.其值必须<1.0
FuzzyQuery query=new FuzzyQuery(new Term(“content”,”work”),0.1f);
其中prefixLength表示要有多少个前缀字母必须完全匹配
FuzzyQuery query=new FuzzyQuery(new Term(“content”,”work”),0.1f,1);
* 表示0到多个字符
? 表示一个单一的字符
WildcardQuery query=new WildcardQuery(new Term(“content”,”?qq*”));
效果和TermQuery相同
SpanTermQuery query=new SpanTermQuery(new Term(“content”,”abc”));
从Field内容的起始位置开始,在一个固定的宽度内查找所指定的词条
SpanFirstQuery query=new SpanFirstQuery(new Term(“content”,”abc”),3);//是第3个word,不是byte
SpanNearQuery相当与PhaseQuery
SpanTermQuery people=new SpanTermQuery(new Term(“content”,”mary”));
SpanTermQuery how=new SpanTermQuery(new Term(“content”,”poor”));
SpanNearQuery query=new SpanNearQuery(new SpanQuery[]{people,how},3,false);
把所有SpanQuery的结果合起来
SpanTermQuery s1=new SpanTermQuery(new Term(“content”,”aa”);
SpanTermQuery s2=new SpanTermQuery(new Term(“content”,”cc”);
SpanTermQuery s3=new SpanTermQuery(new Term(“content”,”gg”);
SpanTermQuery s4=new SpanTermQuery(new Term(“content”,”kk”);
SpanNearQuery query1=new SpanNearQuery(new SpanQuery[]{s1,s2},1,false);
SpanNearQuery query2=new SpanNearQuery(new SpanQuery[]{s3,s4},3,false);
SpanOrQuery query=new SpanOrQuery(new SpanQuery[]{query1,query2});
从第1个SpanQuery的查询结果中,去掉第2个SpanQuery的查询结果
SpanTermQuery s1=new SpanTermQuery(new Term(“content”,”aa”);
SpanFirstQuery query1=new SpanFirstQuery(s1,3);
SpanTermQuery s3=new SpanTermQuery(new Term(“content”,”gg”);
SpanTermQuery s4=new SpanTermQuery(new Term(“content”,”kk”);
SpanNearQuery query2=new SpanNearQuery(new SpanQuery[]{s3,s4},4,false);
SpanNotQuery query=new SpanNotQuery(query1,query2);
String regex="http://[a-z]{1,3}\\.abc\\.com/.*";
RegexQuery query=new RegexQuery(new Term("url",regex));
通过searcher.explain(Query query, int doc)方法可以查看某个文档的得分的具体构成。
在Lucene中score简单说是由 tf * idf * boost * lengthNorm计算得出的。
1) tf:Term Frequency.词条频率,是查询的词在文档中出现的次数的平方根
2) idf:表示反转文档频率,Math.log(numDocs/(double)(docFreq+1))+1.0 docDocs表示当前检索的词条的文档总数, numDocs表示索引中总共的文档数量
3) boost:激励因子,可以通过setBoost方法设置,需要说明的通过field和doc都可以设置,所设置的值会同时起作用 。默认为1.boost的值是在索引建立的时候已经写入了,而不像其他计算得分的因子是在查询时实时得出的。因此,一旦boost值被写入,就不能修改它,除非重新建立文档索引。
4) lengthNorm:是由搜索的field的长度决定了,越长文档的分值越低。
1. write.lock
2. commit.lock