package com.product.lucene.service;
|
|
import com.alibaba.fastjson.JSONObject;
|
import com.product.common.lang.StringUtils;
|
import com.product.core.dao.BaseDao;
|
import com.product.core.entity.FieldSetEntity;
|
import com.product.core.permission.PermissionService;
|
import com.product.core.websocket.config.CmnConst;
|
import com.product.lucene.util.FileUtils;
|
import com.product.util.BaseUtil;
|
|
import org.apache.lucene.analysis.cn.smart.SmartChineseAnalyzer;
|
import org.apache.lucene.document.*;
|
import org.apache.lucene.index.IndexWriter;
|
import org.apache.lucene.index.Term;
|
import org.apache.lucene.queryparser.classic.MultiFieldQueryParser;
|
import org.apache.lucene.queryparser.classic.QueryParser;
|
import org.apache.lucene.search.*;
|
import org.apache.lucene.search.highlight.Fragmenter;
|
import org.apache.lucene.search.highlight.Highlighter;
|
import org.apache.lucene.search.highlight.QueryScorer;
|
import org.apache.lucene.search.highlight.SimpleFragmenter;
|
import org.apache.lucene.search.highlight.SimpleHTMLFormatter;
|
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.stereotype.Service;
|
|
import java.io.File;
|
import java.io.IOException;
|
import java.text.ParseException;
|
import java.util.ArrayList;
|
import java.util.List;
|
|
/**
|
* 文件检索
|
*/
|
@Service("luceneService")
|
public class LuceneService{
|
|
@Autowired
|
BaseDao baseDao;
|
|
@Autowired
|
private IndexWriter indexWriter;
|
|
@Autowired
|
PermissionService permissionService;
|
|
@Autowired
|
private SearcherManager searcherManager;
|
|
/**
|
* 创建索引
|
* @param fse
|
* @throws IOException
|
*/
|
public void createdIndex(FieldSetEntity fse) {
|
String function_uuid=fse.getString("function_uuid"); //获取功能
|
File file=(File)fse.getObject("file"); //获取附件
|
|
//获取全文检索配置
|
FieldSetEntity fseConfig=baseDao.getFieldSetEntityByFilter("product_sys_document_search", "function_uuid=?", new Object[] {function_uuid}, false);
|
if (fseConfig!=null) {
|
String table_uuid=fseConfig.getString("table_name");
|
|
//获取缓存表配置
|
FieldSetEntity fseTable=baseDao.getFieldSetEntity("product_sys_datamodel_table", table_uuid, false);
|
if (fseTable!=null) {
|
|
//获取附件uuids
|
String attachments=fse.getString("attachment_uuid");
|
if (!StringUtils.isEmpty(attachments)) {
|
|
//遍历获取附件信息
|
String [] attachment=attachments.split(",");
|
List<Document> docs=new ArrayList<>();
|
for (int i = 0; i < attachment.length; i++) {
|
|
//获取附件信息
|
FieldSetEntity fseAttachment=baseDao.getFieldSetEntity("product_sys_attachments", attachment[i], false);
|
if (fseAttachment!=null) {
|
|
if (file!=null) {
|
//生成索引信息
|
Document doc=new Document();
|
doc.add(new StringField("uuid", attachment[i], Field.Store.YES)); //附件UUID
|
doc.add(new TextField("function_uuid", function_uuid, Field.Store.YES)); //功能UUID
|
doc.add(new TextField("file_name", fseAttachment.getString("file_name"), Field.Store.YES)); //文件名
|
doc.add(new TextField("file_content", FileUtils.FileToString(file), Field.Store.YES)); //文件内内容
|
docs.add(doc);
|
}
|
}
|
}
|
//写入索引
|
try {
|
indexWriter.addDocuments(docs);
|
indexWriter.commit();
|
} catch (IOException e) {
|
e.printStackTrace();
|
}
|
}
|
}
|
}
|
file.delete();
|
}
|
|
|
/**
|
* 文档检索
|
* @param fse
|
* @return
|
* @throws Exception
|
* @throws ParseException
|
*/
|
public JSONObject searchProduct(FieldSetEntity fse) throws Exception, ParseException {
|
searcherManager.maybeRefresh();
|
IndexSearcher indexSearcher = searcherManager.acquire();
|
|
//文档信息汇总
|
List<JSONObject> jsonTotal=new ArrayList<>();
|
JSONObject jsonReturn=new JSONObject();
|
|
// 模糊匹配,匹配词
|
String search_key=fse.getString("search_key");
|
if (!BaseUtil.strIsNull(search_key)) {
|
//查询解析器
|
QueryParser parser = new MultiFieldQueryParser(new String [] {"file_name","file_content"}, new SmartChineseAnalyzer());
|
Query query = parser.parse(search_key);
|
|
//高亮格式
|
SimpleHTMLFormatter simpleHTMLFormatter = new SimpleHTMLFormatter("<span style='color:red'>", "</span>");
|
//高亮匹配器
|
Highlighter highlighter = new Highlighter(simpleHTMLFormatter, new QueryScorer(query));
|
Fragmenter fragmenter = new SimpleFragmenter(100);
|
highlighter.setTextFragmenter(fragmenter);
|
|
//分页查询文档
|
TopDocs topDocs = searchByPage(fse.getInteger("cpage"), fse.getInteger("pagesize"), indexSearcher, query);
|
|
ScoreDoc[] hits = topDocs.scoreDocs;
|
for (int i = 0; i < hits.length; i++) {
|
Document doc = indexSearcher.doc(hits[i].doc);
|
JSONObject json=new JSONObject();
|
if (!StringUtils.isEmpty(doc.get("function_uuid"))) {
|
getConfig(json, doc.get("function_uuid"), doc.get("uuid"));
|
}
|
json.put("function_uuid", doc.get("function_uuid"));
|
|
// 内容增加高亮显示
|
String file_name=highlighter.getBestFragment(new SmartChineseAnalyzer(), "file_name",doc.get("file_name"));
|
if (StringUtils.isEmpty(file_name)) {
|
file_name=doc.get("file_name");
|
}
|
String file_content=highlighter.getBestFragment(new SmartChineseAnalyzer(), "file_content",doc.get("file_content"));
|
if (StringUtils.isEmpty(file_content)) {
|
file_content=doc.get("file_content");
|
}
|
json.put("file_name", file_name);
|
json.put("file_content", file_content);
|
jsonTotal.add(json);
|
}
|
|
jsonReturn.put("totalCount", topDocs.totalHits.value);
|
}
|
|
jsonReturn.put("data", jsonTotal);
|
return jsonReturn;
|
}
|
|
/**
|
* 获取文档检索配置信息(权限,功能名称,跳转按钮)
|
* @param json
|
* @param function_uuid
|
* @param service_uuid
|
*/
|
public void getConfig(JSONObject json, String function_uuid, String uuid) {
|
|
FieldSetEntity fseConfig=baseDao.getFieldSetEntityByFilter("product_sys_document_search", "function_uuid=?", new Object[] {function_uuid}, false);
|
if (fseConfig!=null) {
|
|
FieldSetEntity fseFunction=baseDao.getFieldSetEntity("product_sys_functions", function_uuid, false);
|
|
//获取权限过滤字段
|
String org_fields=fseConfig.getString("org_fileds");
|
String user_fields=fseConfig.getString("user_fileds");
|
|
//获取附件信息
|
FieldSetEntity fseAttachment=baseDao.getFieldSetEntity("product_sys_attachments", uuid, false);
|
baseDao.loadPromptData(fseAttachment);
|
if (fseAttachment!=null) {
|
StringBuilder filter=new StringBuilder();
|
filter.append(fseAttachment.getString("attachment_data_field"));
|
filter.append(" =? ");
|
if (StringUtils.isEmpty(org_fields)) {
|
if (!StringUtils.isEmpty(user_fields)) {
|
filter.append(" AND ");
|
filter.append(permissionService.getDataFilter(fseAttachment.getString("attachment_data_table"), user_fields));
|
}
|
}else {
|
if (StringUtils.isEmpty(user_fields)) {
|
filter.append(" AND ");
|
filter.append(permissionService.getDataFilter(org_fields));
|
}else {
|
filter.append(" AND ");
|
filter.append(permissionService.getDataFilter(fseAttachment.getString("attachment_data_table"), user_fields, org_fields));
|
}
|
}
|
|
|
//获取原数据
|
FieldSetEntity fseService=baseDao.getFieldSetEntityByFilter(fseAttachment.getString("attachment_data_table"), filter.toString(), new Object[] {uuid}, false);
|
if (fseService==null) {//权限过滤无原数据
|
FieldSetEntity fseService2=baseDao.getFieldSetEntityByFilter(fseAttachment.getString("attachment_data_table"), fseAttachment.getString("attachment_data_field")+"=?", new Object[] {uuid}, false);
|
if (fseService2==null) {
|
// json.put("date_time", fseService2.getString(fseConfig.getString("time_field")));
|
json.put("title", "无相关业务数据");
|
json.put("function_name", fseFunction.getString("function_name"));
|
json.put("is_perssion", 1);
|
}else {
|
json.put("service_uuid", fseService2.getString("uuid"));
|
json.put("date_time", fseService2.getString(fseConfig.getString("time_field")));
|
json.put("title", fseService2.getString(fseConfig.getString("title_field")));
|
json.put("function_name", fseFunction.getString("function_name"));
|
json.put("is_perssion", 0);
|
}
|
|
}else {
|
json.put("service_uuid", fseService.getString("uuid"));
|
json.put("date_time", fseService.getString(fseConfig.getString("time_field")));
|
json.put("title", fseService.getString(fseConfig.getString("title_field")));
|
json.put("function_name", fseFunction.getString("function_name"));
|
}
|
json.put("created_by", fseAttachment.getString(CmnConst.CREATED_BY));
|
}
|
}
|
}
|
|
|
/**
|
* 文件检索查询分页
|
* @param cpage 当前页
|
* @param pagesize 每页大小
|
* @param searcher 查询器
|
* @param query 查询对象
|
* @return
|
* @throws IOException
|
*/
|
private TopDocs searchByPage(int cpage,int pagesize, IndexSearcher searcher, Query query) throws IOException {
|
TopDocs result = null;
|
if(query == null){
|
System.out.println(" Query is null return null ");
|
return null;
|
}
|
ScoreDoc before = null;
|
if(cpage != 1){
|
TopDocs docsBefore = searcher.search(query, (cpage-1)*pagesize);
|
ScoreDoc[] scoreDocs = docsBefore.scoreDocs;
|
if(scoreDocs.length > 0){
|
before = scoreDocs[scoreDocs.length - 1];
|
}
|
}
|
result = searcher.searchAfter(before, query, pagesize);
|
return result;
|
}
|
|
/**
|
* 根据附件uuid删除索引
|
* @param uuid
|
* @throws IOException
|
*/
|
public void deleteIndexByUUID(String uuid) throws IOException {
|
indexWriter.deleteDocuments(new Term("uuid",uuid));
|
indexWriter.commit();
|
}
|
}
|