大家好,分词功能已经实现,但客户需要对搜索结果进一步进行分类筛选,我找了资料没有找到满意的。
代码如下:
bigType和smallType是大小分类,用整型数字表示
private void addOrUpIndex(ArticleEntity entity) {
IndexWriter indexWriter = null;
IndexReader indexReader = null;
Directory directory = null;
Analyzer analyzer = null;
try {
//创建索引目录文件
File indexFile = new File(config.getIndexLibrary());
File[] files = indexFile.listFiles();
// 1. 创建分词器,分析文档,对文档进行分词
analyzer = new IKAnalyzer();
// 2. 创建Directory对象,声明索引库的位置
directory = FSDirectory.open(Paths.get(config.getIndexLibrary()));
// 3. 创建IndexWriteConfig对象,写入索引需要的配置
IndexWriterConfig writerConfig = new IndexWriterConfig(analyzer);
// 4.创建IndexWriter写入对象
indexWriter = new IndexWriter(directory, writerConfig);
// 5.写入到索引库,通过IndexWriter添加文档对象document
Document doc = new Document();
//查询是否有该索引,没有添加,有则更新
TopDocs topDocs = null;
//判断索引目录文件是否存在文件,如果没有文件,则为首次添加,有文件,则查询id是否已经存在
if (files != null && files.length != 0) {
//创建查询对象
QueryParser queryParser = new QueryParser("id", analyzer);
Query query = queryParser.parse(String.valueOf(entity.getId()));
indexReader = DirectoryReader.open(directory);
IndexSearcher indexSearcher = new IndexSearcher(indexReader);
//查询获取命中条目
topDocs = indexSearcher.search(query, 1);
}
//StringField 不分词 直接建索引 存储
doc.add(new StringField("id", String.valueOf(entity.getId()), Field.Store.YES));
//TextField 分词 建索引 存储
doc.add(new TextField("title", entity.getTitle(), Field.Store.YES));
//TextField 分词 建索引 存储
doc.add(new TextField("content", entity.getContent(), Field.Store.YES));
doc.add(new StoredField("bigType", entity.getBigType()));
doc.add(new StoredField("smallType", entity.getSmallType()));
//如果没有查询结果,添加
if (topDocs != null && topDocs.totalHits.value == 0) {
indexWriter.addDocument(doc);
//否则,更新
} else {
indexWriter.updateDocument(new Term("id", String.valueOf(entity.getId())), doc);
}
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException("添加索引库出错:" + e.getMessage());
} finally {
if (indexWriter != null) {
try {
indexWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (indexReader != null) {
try {
indexReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (directory != null) {
try {
directory.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (analyzer != null) {
analyzer.close();
}
}
}
public PageData<ArticleEntity> fullTextSearch(String keyWord, Integer page, Integer limit) {
List<ArticleEntity> searchList = new ArrayList<>(10);
PageData<ArticleEntity> pageData = new PageData<>();
File indexFile = new File(config.getIndexLibrary());
File[] files = indexFile.listFiles();
//沒有索引文件,不然沒有查詢結果
if (files == null || files.length == 0) {
pageData.setCount(0);
pageData.setTotalPage(0);
pageData.setCurrentPage(page);
pageData.setResult(new ArrayList<>());
return pageData;
}
IndexReader indexReader = null;
Directory directory = null;
try (Analyzer analyzer = new IKAnalyzer()) {
directory = FSDirectory.open(Paths.get(config.getIndexLibrary()));
//多项查询条件
QueryParser queryParser = new MultiFieldQueryParser(new String[]{"title", "content"}, analyzer);
//单项
//QueryParser queryParser = new QueryParser("title", analyzer);
Query query = queryParser.parse(!StringUtils.isEmpty(keyWord) ? keyWord : "*:*");
indexReader = DirectoryReader.open(directory);
//索引查询对象
IndexSearcher indexSearcher = new IndexSearcher(indexReader);
TopDocs topDocs = indexSearcher.search(query, 1);
//获取条数
int total = (int) topDocs.totalHits.value;
pageData.setCount(total);
int realPage = total % limit == 0 ? total / limit : total / limit + 1;
pageData.setTotalPage(realPage);
//获取结果集
ScoreDoc lastSd = null;
if (page > 1) {
int num = limit * (page - 1);
TopDocs tds = indexSearcher.search(query, num);
lastSd = tds.scoreDocs[num - 1];
}
//通过最后一个元素去搜索下一页的元素
TopDocs tds = indexSearcher.searchAfter(lastSd, query, limit);
QueryScorer queryScorer = new QueryScorer(query);
//最佳摘要
SimpleSpanFragmenter fragmenter = new SimpleSpanFragmenter(queryScorer, 200);
//高亮前后标签
SimpleHTMLFormatter formatter = new SimpleHTMLFormatter("<b><font color='red'>", "</font></b>");
//高亮对象
Highlighter highlighter = new Highlighter(formatter, queryScorer);
//设置高亮最佳摘要
highlighter.setTextFragmenter(fragmenter);
//遍历查询结果 把标题和内容替换为带高亮的最佳摘要
for (ScoreDoc sd : tds.scoreDocs) {
Document doc = indexSearcher.doc(sd.doc);
ArticleEntity articleEntity = new ArticleEntity();
Integer id = Integer.parseInt(doc.get("id"));
//获取标题的最佳摘要
String titleBestFragment = highlighter.getBestFragment(analyzer, "title", doc.get("title"));
titleBestFragment = StringUtils.isEmpty(titleBestFragment) ? doc.get("title") : titleBestFragment;
//获取文章内容的最佳摘要
String contentBestFragment = highlighter.getBestFragment(analyzer, "content", doc.get("content"));
contentBestFragment = StringUtils.isEmpty(contentBestFragment) ? doc.get("content") : contentBestFragment;
articleEntity.setId(id);
articleEntity.setTitle(titleBestFragment);
articleEntity.setContent(contentBestFragment);
searchList.add(articleEntity);
}
pageData.setCurrentPage(page);
pageData.setResult(searchList);
return pageData;
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException("全文檢索出错:" + e.getMessage());
} finally {
if (indexReader != null) {
try {
indexReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (directory != null) {
try {
directory.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
fullTextSearch方法只实现了分词搜索功能,但不知道怎么加上分类搜索,请指点,谢谢!
IKAnalyzer
Java