package com.lucene.util; import com.zxf.lucene.analyzer.lucene.IKAnalyzer; import com.zxf.lucene.common.consts.SortType; import com.zxf.lucene.dto.DocumentSearchDto; import org.apache.lucene.analysis.Analyzer; import org.apache.lucene.document.Document; import org.apache.lucene.index.*; import org.apache.lucene.queryparser.classic.ParseException; 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 java.io.File; import java.io.IOException; import java.nio.file.Paths; import java.util.*; /** * Created by jiangyang on 2019/3/8. */ public class LuceneQueryAndDeleteDemo { /** * 根據提交刪除索引 * @param fieldKey * @param value */ public void deleteDocumentsByFieldKeyAndNumber(String fieldKey,long value){ Query query = new DocValuesNumbersQuery(fieldKey,value); try { String dir = "索引文件存放路徑"; IndexWriter writer = getIndexWriterInstance(dir); writer.deleteDocuments(query); writer.commit(); } catch (IOException e) { e.printStackTrace(); } } /** * 查詢過程省略空null判斷 * @param dto * DocumentSearchDto中封裝的查詢條件 * 查詢條件 private BooleanQuery.Builder builder; * 須要查詢的屬性字段 private Set<String> keys; * 無序 正序 倒序 private Integer sortType; * 用戶排序字段名稱 private String sortFieldKey; * 用戶排序的字段類型private SortField.Type sortFieldType; * @return */ public List<Map> searchPageData(DocumentSearchDto dto){ BooleanQuery.Builder builder = dto.getBuilder(); Set<String> keys = dto.getKeys(); if(builder == null || keys == null || keys.isEmpty()){ return null; } Integer sortType = dto.getSortType(); String sortTypeName = SortType.getName(sortType); String sortFieldKey = dto.getSortFieldKey(); SortField.Type sortFieldType = dto.getSortFieldType(); IndexReader reader = null; try { String dirPath = "索引文件存放位置"; IndexWriter writer = getIndexWriterInstance(dirPath); Directory dir = writer.getDirectory(); reader = DirectoryReader.open(dir); } catch (Exception e) { e.printStackTrace(); return null; } IndexSearcher indexSearcher = new IndexSearcher(reader); int total = 0; BooleanQuery query = builder.build(); try { total = indexSearcher.count(query); } catch (IOException e) { e.printStackTrace(); return null; } if(total == 0){ return null; } int pageSize = dto.getPageSize(); int totalPage = (int)Math.ceil(total*1.0/pageSize); int pageNum = dto.getPageNum(); if( pageNum > totalPage ){ return null; } int topCount = pageNum*pageSize; TopDocs topDocs = null; //排序 try { if(SortType.NOTORDER.code.equals(sortType)){ topDocs = indexSearcher.search(query, topCount); }else if(SortType.NORMALORDER.code.equals(sortType)){ topDocs = indexSearcher.search(query, topCount,new Sort(new SortField(sortFieldKey, sortFieldType, false))); }else{ topDocs = indexSearcher.search(query, topCount,new Sort(new SortField(sortFieldKey,sortFieldType, true))); } } catch (Exception e) { e.printStackTrace(); return null; } //裝配查詢出的數據 List<Document> docmentList = getDocmentList(topDocs, pageNum, pageSize, indexSearcher); List<Map> result = getResult(docmentList, keys, total); try { reader.close(); } catch (IOException e) { e.printStackTrace(); } return result; } /** * 多條件查詢時,條件封裝 * @return */ private BooleanQuery.Builder getQueryBuilder() { //必須知足此條件BooleanClause.Occur.MUST //必須不知足此條件BooleanClause.Occur.MUST_NOT //過濾BooleanClause.Occur.FILTER //或的關係BooleanClause.Occur.SHOULD String searchKey = "我叫張三,我是查詢關鍵詞"; BooleanQuery.Builder builder = new BooleanQuery.Builder(); //數值型的查詢條件 Query query = new DocValuesNumbersQuery("id", 123L); builder.add(query, BooleanClause.Occur.MUST); String dirPath = "索引文件存放路徑"; Analyzer analyzer =getIndexWriterInstance(dirPath).getAnalyzer(); //保存的時候採用的什麼分詞器分詞,查詢的時候須要用一樣的分詞器將查詢關鍵詞分詞後查詢 QueryParser parser = new QueryParser("name", analyzer); try { query = parser.parse(searchKey); } catch (ParseException e) { e.printStackTrace(); return null; } builder.add(query, BooleanClause.Occur.MUST); //模糊查詢 當對應字段字符串沒有進行分詞時,使用new WildcardQuery((new Term("name", "*張*"))); Query sortNameQuery = new WildcardQuery((new Term("name", "*張*"))); builder.add(sortNameQuery, BooleanClause.Occur.MUST); return builder; } /** * 獲取Document數據集 * @param topDocs * @param pageNum * @param pageSize * @param indexSearcher * @return */ private List<Document> getDocmentList(TopDocs topDocs, int pageNum, int pageSize,IndexSearcher indexSearcher) { if(topDocs == null){ return Collections.emptyList(); } ScoreDoc[] scoreDocs = topDocs.scoreDocs; if(scoreDocs == null || scoreDocs.length == 0){ return Collections.emptyList(); } int total = scoreDocs.length; List<Document> documents = new ArrayList<>(pageSize); int start = (pageNum-1)*pageSize; for (int i=start;i<total;i++) { try { Document doc = indexSearcher.doc(scoreDocs[i].doc); documents.add(doc); } catch (IOException e) { e.printStackTrace(); } } return documents; } private List<Map> getResult(List<Document> docmentList, Set<String> keys,int total) { if(docmentList == null || docmentList.isEmpty()){ return null; } List list = new ArrayList(); for(Document document:docmentList){ Map map = new HashMap(); for(String key:keys){ map.put(key,document.get(key)); } if(!map.isEmpty()){ list.add(map); } } return list; } /** * @param dir 存放索引文件的 文件存放路徑 * @return */ public IndexWriter getIndexWriterInstance(String dir) { File file = new File(dir); if (!file.exists()) { file.mkdirs(); } try{ Directory directory = FSDirectory.open(Paths.get(dir)); IKAnalyzer ikAnalyzer = new IKAnalyzer(); //設置相應的分詞器 IndexWriterConfig indexWriterConfig = new IndexWriterConfig(ikAnalyzer); return new IndexWriter(directory, indexWriterConfig); } catch (Exception e) { e.printStackTrace(); } return null; } }