模板:
Occur 用于表示布尔查询子句关系的类,包括:
Occur.MUST,Occur.MUST_NOT,Occur.SHOULD。
MUST和MUST:取得连个查询子句的交集。 AND
MUST和MUST_NOT:包含MUST并且查询结果中不包含MUST_NOT的检索结果。 排除第二个
SHOULD与SHOULD,表示“或”关系,最终检索结果为所有检索子句的并集。 OR
一般不单独使用,因为单独就不应使用BooleanQuery了。
使用时注意:
单独使用MUST_NOT:无意义,检索无结果。(也不报错)
单独使用SHOULD:结果相当于MUST。
MUST_NOT和MUST_NOT:无意义,检索无结果。(也不报错)
SHOULD和MUST_NOT: 此时SHOULD相当于MUST,结果同MUST和MUST_NOT。
MUST和SHOULD:此时SHOULD无意义,结果为MUST子句的检索结果。
@Test
public void testBooleanQuery() throws Exception{
//search("java AND lucene");
BooleanQuery query = new BooleanQuery();
TermQuery q1 = new TermQuery(new Term("content","java"));//2,3
query.add(q1,Occur.MUST);
TermRangeQuery q2 = new TermRangeQuery("inputtime",new BytesRef("20160229"),new BytesRef("20160302"), true, false);
query.add(q2,Occur.MUST_NOT);//1,2
//Occur.MUST 必须包含
//Occur.MUST_NOT 必须排除
//Occur.SHOULD 可以可无
search(query);
}
目标:查询出标题中包括One及内容中包括java的文档;
下面两种情况均可:
title:one && content:java
title:one AND content:java
查询出标题中包括One但内容中不包括java的文档;
默认情况下分词组合即为逻辑或(OR)方式。
下面三种情况均可:
title:one || content:java
title:one OR content:java
title:one content:java
查询出标题中包括One但内容中不包括java的文档;
下面两种情况均可:
title:one ! content:java
title:one NOT content:java
目标:查询出标题中包括One但内容中不包括java的文档;
+title:one -content:title
Luence允许我们在组合查询中,指定某一个词的相关性权重值,从而可以让得到相关性高的结果;
要提升一个词的相关性权重,则可以在关键词的后面添加^n来实现。
比如查询jakarta apache,如果要把jakarta 的相关性提高,则可以改为jakarta^4 apache
相关性权重也可以用于词组查询,比如"jakarta apache"^4 "Apache Lucene" 将把与jakarta apache词组最相关的优先排列出来;
相关性权重值默认为1,一般要提升权重时均设置为大于1的整数;该值也可以为0-1的小数,但不能为负数。
@Test
public void testWeightQuery() throws Exception{
//查询所有
search("java lucene^10");
/*PhraseQuery query = new PhraseQuery();
query.add(new Term("content","hello"));
query.add(new Term("content","world"));
search(query);*/
}
由于| & ! + - ( ) 等符号在查询表达式中被用做关键字,因此要查询这些字符必须使用\来进行转义处理。
当前Lucene查询中的特殊字符:+ - && || ! ( ) { } [ ] ^ " ~ * ? : \
比如,要查询包括(1+1):2 的文档,需要使用到如下表达式:
\(1\+1\)\:2
使用括号()对查询表示式分组Grouping
Lucene查询语法中支持通过()来对查询表达式进行分组,从而组合出各种复杂的查询。
1、查询出标题中包括one或two,但内容中不包括java的文档;
Query query=parser.parse("title:(one OR two) NOT content:java");
package highLucene;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.FieldType;
import org.apache.lucene.index.*;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.search.*;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.util.BytesRef;
import org.apache.lucene.util.Version;
import org.junit.Test;
import java.io.File;
public class highLuceneTest {
String path="D:/workforce/lucene/crud"; //创建文件路径
Version version=Version.LUCENE_4_10_4; //创建Lucene的版本
String cn="我对什么书表示兴趣,父亲就把那部书放在我书桌上,有时他得爬梯到书橱高处去拿; 假如我长期不读,那部书就不见了---这就等于谴责。";
String en="When I expressed interest in any book, my father put it on my desk. Sometimes he had to climb the ladder to get it from the top of the bookcase. If I didn't read it for a long time, it would disappear - that would be condemnation.";
//设置内容
String content1="走好选择的路,别选择好走的路,你才能拥有真正的自己。";
String content2="惟有身处卑微的人,最有机缘看到世态人情的真相。一个人不想攀高就不怕下跌,也不用倾轧排挤,可以保其天真,成其自然,潜心一志完成自己能做的事。";
String content3="我甘心当个“零”,人家不把我当个东西,我正好可以把看不起我的人看个透 ";
//Lucene的录入
@Test
public void testLucene() throws Exception{
//1.定义Lucene存放文件的位置
Directory directory= FSDirectory.open(new File(path));
//2.配置分词对象
Analyzer analyzer=new StandardAnalyzer();
//3.配置对象
IndexWriterConfig config=new IndexWriterConfig(version,analyzer);
config.setOpenMode(IndexWriterConfig.OpenMode.CREATE);//每次都重新创建
IndexWriter writer=new IndexWriter(directory,config);
//4.往库里写入内容
FieldType type=new FieldType();
type.setStored(true);//可存储
type.setIndexed(true);//存储索引
type.setTokenized(true);//设置分词
//创建文档对象
Document doc=new Document();
doc.add(new Field("title","doc1",type));
doc.add(new Field("content",content1,type));
doc.add(new Field("inputtime","20190307",type));
writer.addDocument(doc);
Document doc2=new Document();
doc2.add(new Field("title","doc2",type));
doc2.add(new Field("content",content2,type));
doc2.add(new Field("inputtime","20190308",type));
writer.addDocument(doc2);
Document doc3=new Document();
doc3.add(new Field("title","doc3",type));
doc3.add(new Field("content",en,type));
doc3.add(new Field("inputtime","20190309",type));
writer.addDocument(doc3);
//5.提交资源
//6.关闭资源
writer.close();
}
//Lucene的查询
public void testSearch(String content)throws Exception{
//1.定义Lucene存放文件的位置
Directory directory=FSDirectory.open(new File(path));
//2.创建Reader
IndexReader reader= DirectoryReader.open(directory);
//3.创建读取对象
IndexSearcher searcher=new IndexSearcher(reader);
//第一个参数表示:在哪个字段查询内容
//第二参数:分词对象
Analyzer analyzer=new StandardAnalyzer();
QueryParser parser=new QueryParser("content",analyzer);
Query query=parser.parse(content);
System.out.println(query.getClass());
//第二个参数表示符合条件的前n条记录
TopDocs tds=searcher.search(query,10000);
System.out.println("总共命中次数: "+tds.totalHits);
ScoreDoc[] scoreDocs=tds.scoreDocs;
ScoreDoc scoredoc=null;
Document doc=null;
for (int i=0;i<scoreDocs.length;i++){
scoredoc=scoreDocs[i];
doc=searcher.doc(scoredoc.doc);
System.out.println("文档分数:"+scoredoc.score+" "+"文档编号:"+scoredoc.doc+" "+"title:"+doc.get("title")+" "+"content:"+doc.get("content"));
// System.out.println("文档编号:"+scoredoc.doc);
// doc=searcher.doc(scoredoc.doc); //根据编号获取文档
// System.out.println("title:"+doc.get("title")); //获取标题
// System.out.println("content:"+doc.get("content"));//获取文档内容
System.out.println("-------------------------");
}
}
//Lucene的查询
public void testSearch(Query query)throws Exception{
System.out.println(query);
//1.定义Lucene存放文件的位置
Directory directory=FSDirectory.open(new File(path));
//2.创建Reader
IndexReader reader= DirectoryReader.open(directory);
//3.创建读取对象
IndexSearcher searcher=new IndexSearcher(reader);
//第一个参数表示:在哪个字段查询内容
//第二参数:分词对象
Analyzer analyzer=new StandardAnalyzer();
//第二个参数表示符合条件的前n条记录
TopDocs tds=searcher.search(query,10000);
System.out.println("总共命中次数: "+tds.totalHits);
ScoreDoc[] scoreDocs=tds.scoreDocs;
ScoreDoc scoredoc=null;
Document doc=null;
for (int i=0;i<scoreDocs.length;i++){
scoredoc=scoreDocs[i];
doc=searcher.doc(scoredoc.doc);
System.out.println("文档分数:"+scoredoc.score+" "+"文档编号:"+scoredoc.doc+" "+"title:"+doc.get("title")+" "+"content:"+doc.get("content"));
// System.out.println("文档编号:"+scoredoc.doc);
// doc=searcher.doc(scoredoc.doc); //根据编号获取文档
// System.out.println("title:"+doc.get("title")); //获取标题
// System.out.println("content:"+doc.get("content"));//获取文档内容
System.out.println("-------------------------");
}
}
//组合查询
@Test
public void testArrest( )throws Exception{
testSearch("book^10 && interest");
System.out.println("*************************************");
System.out.println("*************************************");
System.out.println("*************************************");
BooleanQuery query=new BooleanQuery();
TermRangeQuery q1=new TermRangeQuery("inputtime",new BytesRef("20190307"),new BytesRef("20190309"),true,true);
TermQuery q2=new TermQuery(new Term("content","book && interest"));
q1.setBoost(10f);//设置权重
query.add(q1, BooleanClause.Occur.MUST);
query.add(q2, BooleanClause.Occur.MUST);
testSearch(query);
}
}