+
 新版

IKAnalyzer怎么先分词再分类查询呢?

地北天南 发布于 2023/08/29 10:00
阅读 157
收藏 0

大家好,分词功能已经实现,但客户需要对搜索结果进一步进行分类筛选,我找了资料没有找到满意的。

代码如下:

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方法只实现了分词搜索功能,但不知道怎么加上分类搜索,请指点,谢谢!

加载中
OSCHINA
登录后可查看更多优质内容
返回顶部
顶部