- 说明:数据保存在关系数据库,需要实现增删改查操作。索引数据保存在索引库,也需要实现增删改查操作。
public class CrudTest {
private IndexWriter indexWriter;
@Before
public void before() throws Exception{
// 创建分词器
IKAnalyzer analyzer = new IKAnalyzer();
// 创建写索引需要的配置信息对象
IndexWriterConfig iwc = new IndexWriterConfig(Version.LUCENE_4_10_3, analyzer);
iwc.setOpenMode(IndexWriterConfig.OpenMode.CREATE_OR_APPEND);
// 创建索引库存储的目录
Directory directory = FSDirectory.open(new File("F:\\index"));
// 创建IndexWriter对象,操作索引库
indexWriter = new IndexWriter(directory, iwc);
}
/** 添加文档到索引库 */
@Test
public void save() throws Exception{
// 创建文档对象
Document document = new Document();
// 文档添加Field
document.add(new StringField("id", "5", Field.Store.YES));
document.add(new TextField("name", "lucene solr dubbo", Field.Store.YES));
// 添加到索引库(根据Field创建索引, 保存文档到索引库)
indexWriter.addDocument(document);
// 提交事务
indexWriter.commit();
}
}
1.2.1 根据Term删除索引
- 创建分词器对象(Analyzer),用于分词。
- 创建索引库配置对象(IndexWriterConfig),配置索引库。
- 创建索引库目录对象(Directory),指定索引库位置。
- 创建索引库操作对象(IndexWriter),操作索引库。
- 创建条件对象(Term)。
- 使用IndexWriter对象,执行删除。
- 释放资源。
1.2.2 删除全部索引
- 创建分析器对象(Analyzer),用于分词
- 创建索引库配置对象(IndexWriterConfig),配置索引库
- 创建索引库目录对象(Directory),指定索引库的位置
- 创建索引库操作对象(IndexWriter),操作索引库
- 使用IndexWriter,执行删除
public class CrudTest {
private IndexWriter indexWriter;
@Before
public void before() throws Exception{
// 创建分词器
IKAnalyzer analyzer = new IKAnalyzer();
// 创建写索引需要的配置信息对象
IndexWriterConfig iwc = new IndexWriterConfig(Version.LUCENE_4_10_3, analyzer);
iwc.setOpenMode(IndexWriterConfig.OpenMode.CREATE_OR_APPEND);
// 创建索引库存储的目录
Directory directory = FSDirectory.open(new File("F:\\index"));
// 创建IndexWriter对象,操作索引库
indexWriter = new IndexWriter(directory, iwc);
}
/** 修改索引库中的文档(如果没有Term词就会做添加) */
@Test
public void update() throws Exception{
// 创建文档对象
Document document = new Document();
// 文档添加Field
document.add(new StringField("id", "10", Field.Store.YES));
document.add(new TextField("bookName", "Lucene全文检索", Field.Store.YES));
// 创建Term词
Term term = new Term("id", "10");
// 修改索引库中文档(索引与文档同时修改)
indexWriter.updateDocument(term, document);
// 提交事务
indexWriter.commit();
}
/** 删除索引库中的文档(索引也会删除) */
@Test
public void delete() throws Exception{
// 创建Term词
Term term = new Term("id", "4");
// 删除索引库中文档(索引与文档同时删除)
indexWriter.deleteDocuments(term);
// 提交事务
indexWriter.commit();
}
/** 删除索引库中全部的文档 */
@Test
public void deleteAll() throws Exception{
// 删除索引库中文档
indexWriter.deleteAll();
// 提交事务
indexWriter.commit();
}
}
说明:Lucene是根据Term执行索引的更新,先根据Term执行搜索,搜索到执行更新;搜索不到执行添加。
- 创建分析器对象(Analyzer),用于分词
- 创建索引库配置对象(IndexWriterConfig),配置索引库
- 创建索引库目录对象(Directory),指定索引库的位置
- 创建索引库操作对象(IndexWriter),操作索引库
- 创建文档对象(Document)
- 创建条件对象(Term)
- 使用IndexWriter,执行更新
- 提交事务
- 释放资源
/** 更新索引 */
@Test
public void updateIndex() throws Exception{
// 创建分析器,用于分词
Analyzer analyzer = new IKAnalyzer();
// 创建索引库配置信息对象
IndexWriterConfig iwc = new IndexWriterConfig(Version.LUCENE_4_10_3,analyzer);
// 创建索引库存储目录
Directory directory = FSDirectory.open(new File("F:\\index"));
// 创建IndexWriter,操作索引库
IndexWriter indexWriter = new IndexWriter(directory, iwc);
// 创建文档对象
Document doc = new Document();
// 文档添加域
doc.add(new StringField("id", "9529", Field.Store.YES));
doc.add(new TextField("name", "lucene solr dubbo zookeeper", Field.Store.YES));
// 创建查询条件对象
Term term = new Term("name","lucene");
// 使用indexWriter对象,执行更新
indexWriter.updateDocument(term, doc);
// 提交事务
indexWriter.commit();
// 关闭,释放资源
indexWriter.close();
}
说明:在搜索中关心Query对象的创建。
2.1 query对象的两种创建方式
使用TermQuery
需求:查询图书名称域中包含有java的图书。
/** 定义搜索方法 */
private void search(Query query) throws Exception{
// 查询语法
System.out.println("查询语法:" + query);
// 创建索引库存储目录
Directory directory = FSDirectory.open(new File("F:\\index"));
// 创建IndexReader读取索引库对象
IndexReader indexReader = DirectoryReader.open(directory);
// 创建IndexSearcher,执行搜索索引库
IndexSearcher indexSearcher = new IndexSearcher(indexReader);
/**
* search方法:执行搜索
* 参数一:查询对象
* 参数二:指定搜索结果排序后的前n个(前10个)
*/
TopDocs topDocs = indexSearcher.search(query, 10);
// 处理结果集
System.out.println("总命中的记录数:" + topDocs.totalHits);
// 获取搜索到得文档数组
ScoreDoc[] scoreDocs = topDocs.scoreDocs;
// ScoreDoc对象:只有文档id和分值信息
for (ScoreDoc scoreDoc : scoreDocs){
System.out.println("-------华丽分割线----------");
System.out.println("文档id: " + scoreDoc.doc
+ "\t文档分值:" + scoreDoc.score);
// 根据文档id获取指定的文档
Document doc = indexSearcher.doc(scoreDoc.doc);
System.out.println("图书Id:" + doc.get("id"));
System.out.println("图书名称:" + doc.get("bookName"));
System.out.println("图书价格:" + doc.get("bookPrice"));
System.out.println("图书图片:" + doc.get("bookPic"));
System.out.println("图书描述:" + doc.get("bookDesc"));
}
// 释放资源
indexReader.close();
}
/**
* TermQuery关键词查询
* 需求:查询图书名称域中包含有java的图书。
*/
@Test
public void testTermQuery() throws Exception{
// 创建查询对象
TermQuery q = new TermQuery(new Term("bookName","java"));
// 执行搜索
search(q);
}
使用NumericRangeQuery
需求:查询图书价格在80到100之间的图书。
不包含边界值:
/**
* NumericRangeQuery数值范围查询
* 需求:查询图书价格在80到100之间的图书
*/
@Test
public void testNumericRangeQuery() throws Exception{
// 创建查询对象
/**
* 参数说明
* field:域的名称
* min:最小范围边界值
* max:最大范围边界值
* minInclusive:是否包含最小边界值
* maxInclusive:是否包含最大边界值
*/
Query q = NumericRangeQuery.newDoubleRange("bookPrice",
80d, 100d, false, false);
// 执行搜索
search(q);
}
包含边界值:
/**
* NumericRangeQuery数值范围查询
* 需求:查询图书价格在80到100之间的图书
*/
@Test
public void testNumericRangeQuery() throws Exception{
// 创建查询对象
/**
* 参数说明
* field:域的名称
* min:最小范围边界值
* max:最大范围边界值
* minInclusive:是否包含最小边界值
* maxInclusive:是否包含最大边界值
*/
Query q = NumericRangeQuery.newDoubleRange("bookPrice",
80d, 100d, true, true);
// 执行搜索
search(q);
}
使用BooleanQuery
需求:查询图书名称域中包含有java的图书,并且价格在80到100之间(包含边界值)
/**
* BooleanQuery布尔查询
* 需求:查询图书名称域中包含有java的图书,并且价格在80到100之间(包含边界值)。
*/
@Test
public void testBooleanQuery() throws Exception{
// 创建查询对象一
TermQuery q1 = new TermQuery(new Term("bookName", "java"));
// 创建查询对象二
Query q2 = NumericRangeQuery.newDoubleRange("bookPrice",
80d, 100d, true, true);
// 创建组合查询条件对象
BooleanQuery q = new BooleanQuery();
q.add(q1, BooleanClause.Occur.MUST);
q.add(q2, BooleanClause.Occur.MUST);
// 执行搜索
search(q);
}
2.1.2.1表达式语法
Occur.MUST搜索条件必须满足,相当于AND |
+ |
Occur.SHOULD搜索条件可选,相当于OR |
空 |
Occur.MUST_NOT搜索条件不能满足,相当于NOT非 |
- |
使用QueryParser
需求:查询图书名称域中包含有java,并且图书名称域中包含有lucene的图书
/**
* 使用QueryParser
* 需求:查询图书名称域中包含有java,并且图书名称域中包含有lucene的图书
*/
@Test
public void testQueryParser() throws Exception{
// 创建分析器,用于分词
Analyzer analyzer = new IKAnalyzer();
// 创建QueryParser解析对象
QueryParser queryParser = new QueryParser("bookName",analyzer);
// 解析表达式,创建Query对象
// +bookName:java +bookName:lucene
Query q = queryParser.parse("bookName:java AND bookName:lucene");
// 执行搜索
search(q);
}