package com.product.lucene.service; import com.alibaba.fastjson.JSONObject; import com.product.common.lang.StringUtils; import com.product.core.config.CoreConst; import com.product.core.dao.BaseDao; import com.product.core.entity.FieldSetEntity; import com.product.core.permission.PermissionService; import com.product.core.spring.context.SpringMVCContextHolder; import com.product.lucene.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(CoreConst.FUNCTION_UUID); //获取功能 File file=(File)fse.getObject("file"); //获取附件 //获取全文检索配置 FieldSetEntity fseConfig=baseDao.getFieldSetEntityByFilter(CmnConst.PRODUCT_SYS_DOCUMENT_SEARCH, "function_uuid=?", new Object[] {function_uuid}, false); if (fseConfig!=null) { String table_uuid=fseConfig.getString(CmnConst.TABLE_NAME); //获取缓存表配置 FieldSetEntity fseTable=baseDao.getFieldSetEntity(CoreConst.PRODUCT_SYS_DATAMODEL_TABLE, table_uuid, false); if (fseTable!=null) { //获取附件uuids String attachments=fse.getString(CmnConst.ATTACHMENT_UUID); if (!StringUtils.isEmpty(attachments)) { //遍历获取附件信息 String [] attachment=attachments.split(","); List docs=new ArrayList<>(); for (int i = 0; i < attachment.length; i++) { //获取附件信息 FieldSetEntity fseAttachment=baseDao.getFieldSetEntity(CmnConst.PRODUCT_SYS_ATTACHMENTS, attachment[i], false); if (fseAttachment!=null) { if (file!=null) { //生成索引信息 Document doc=new Document(); doc.add(new StringField(CoreConst.UUID, attachment[i], Field.Store.YES)); //附件UUID doc.add(new TextField(CoreConst.FUNCTION_UUID, function_uuid, Field.Store.YES)); //功能UUID doc.add(new TextField(CmnConst.FILE_NAME, fseAttachment.getString(CmnConst.FILE_NAME), Field.Store.YES)); //文件名 doc.add(new TextField(CmnConst.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 jsonTotal=new ArrayList<>(); JSONObject jsonReturn=new JSONObject(); // 模糊匹配,匹配词 String search_key=fse.getString(CmnConst.SEARCH_KEY); if (!BaseUtil.strIsNull(search_key)) { //查询解析器 QueryParser parser = new MultiFieldQueryParser(new String [] {CmnConst.FILE_NAME,CmnConst.FILE_CONTENT}, new SmartChineseAnalyzer()); Query query = parser.parse(search_key); //高亮格式 SimpleHTMLFormatter simpleHTMLFormatter = new SimpleHTMLFormatter(CmnConst.HIGHLIGHT_BEFORE, CmnConst.HIGHLIGHT_AFTER); //高亮匹配器 Highlighter highlighter = new Highlighter(simpleHTMLFormatter, new QueryScorer(query)); Fragmenter fragmenter = new SimpleFragmenter(100); highlighter.setTextFragmenter(fragmenter); //分页查询文档 TopDocs topDocs = searchByPage(fse.getInteger(CoreConst.CPAGE), fse.getInteger(CoreConst.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(CoreConst.FUNCTION_UUID))) { getConfig(json, doc.get(CoreConst.FUNCTION_UUID), doc.get(CoreConst.UUID)); } json.put(CoreConst.FUNCTION_UUID, doc.get(CoreConst.FUNCTION_UUID)); // 内容增加高亮显示 String file_name=highlighter.getBestFragment(new SmartChineseAnalyzer(), CmnConst.FILE_NAME,doc.get(CmnConst.FILE_NAME)); if (StringUtils.isEmpty(file_name)) { file_name=doc.get(CmnConst.FILE_NAME); } String file_content=highlighter.getBestFragment(new SmartChineseAnalyzer(), CmnConst.FILE_CONTENT,doc.get(CmnConst.FILE_CONTENT)); if (StringUtils.isEmpty(file_content)) { file_content=doc.get(CmnConst.FILE_CONTENT); } json.put(CmnConst.FILE_NAME, file_name); json.put(CmnConst.FILE_CONTENT, file_content); jsonTotal.add(json); } jsonReturn.put(CmnConst.TOTALCOUNT, topDocs.totalHits.value); } jsonReturn.put(CmnConst.DATA, jsonTotal); return jsonReturn; } /** * 获取文档检索配置信息(权限,功能名称,跳转按钮) * * @param json 检索文件对应信息 * @param function_uuid 所属功能UUID * @param service_uuid 附件UUID */ public void getConfig(JSONObject json, String function_uuid, String uuid) { StringBuilder searchConfigSql = new StringBuilder(); searchConfigSql.append("SELECT ") .append(" A.uuid,A.function_uuid,A.function_button_uuid,A.table_name,") .append(" A.attachment_file,A.org_fields,A.user_fields,title_field,time_field,") .append(" B.function_name,C.button_name") .append(" FROM product_sys_document_search A") .append(" LEFT JOIN product_sys_functions B ON A.function_uuid = B.uuid") .append(" LEFT JOIN product_sys_function_buttons C ON A.function_button_uuid = C.uuid") .append(" WHERE A.function_uuid=?"); //获取文档检索配置 FieldSetEntity fseConfig = baseDao.getFieldSetBySQL(searchConfigSql.toString(), new Object[] {function_uuid}, false); if (fseConfig!=null) { //获取跳转按钮 并 判断跳转权限 String buttonName = fseConfig.getString(CoreConst.BUTTON_NAME); if (BaseUtil.strIsNull(buttonName)) { json.put(CmnConst.IS_PERSSION, 2); }else { json.put(CmnConst.SKIPBUTTON, fseConfig.getString(CoreConst.BUTTON_NAME)); } //获取权限过滤字段 String org_fields=fseConfig.getString(CmnConst.ORG_FIELDS); String user_fields=fseConfig.getString(CmnConst.USER_FIELDS); //获取附件信息,结合数据权限字段,生成原数据的过滤SQL FieldSetEntity fseAttachment=baseDao.getFieldSetEntity(CmnConst.PRODUCT_SYS_ATTACHMENTS, uuid, false); baseDao.loadPromptData(fseAttachment); if (fseAttachment!=null) { StringBuilder filter=new StringBuilder(); filter.append(fseAttachment.getString(CmnConst.ATTACHMENT_DATA_FIELD)); filter.append(" =? "); if (StringUtils.isEmpty(org_fields)) { if (!StringUtils.isEmpty(user_fields)) { filter.append(" AND "); filter.append(permissionService.getDataFilter(fseAttachment.getString(CmnConst.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(CmnConst.ATTACHMENT_DATA_TABLE), user_fields, org_fields)); } } //获取原数据 FieldSetEntity fseService=baseDao.getFieldSetEntityByFilter(fseAttachment.getString(CmnConst.ATTACHMENT_DATA_TABLE), filter.toString(), new Object[] {uuid}, false); if (fseService==null) { //获取无权限过滤的原数据 FieldSetEntity fseService2=baseDao.getFieldSetEntityByFilter(fseAttachment.getString(CmnConst.ATTACHMENT_DATA_TABLE), fseAttachment.getString(CmnConst.ATTACHMENT_DATA_FIELD)+"=?", new Object[] {uuid}, false); if (fseService2==null) { json.put(CmnConst.TITLE, "业务数据不存在"); json.put(CmnConst.IS_PERSSION, 1); }else { json.put(CmnConst.SERVICE_UUID, fseService2.getString(CoreConst.UUID)); json.put(CmnConst.DATE_TIME, fseService2.getString(fseConfig.getString(CmnConst.TIME_FIELD))); json.put(CmnConst.TITLE, fseService2.getString(fseConfig.getString(CmnConst.TITLE_FIELD))); json.put(CmnConst.IS_PERSSION, 0); } }else { //判断是否为文档管理功能,并处理单位文档和个人文档权限 if("e4fa2c88-88a4-4ef4-9020-ebbe0440b4cf".equals(function_uuid)) { if(!SpringMVCContextHolder.getCurrentUserId().equals(fseService.getString(CoreConst.CREATED_BY))) { json.put(CmnConst.IS_PERSSION, 0); } }else if ("01513ff6-c758-4384-b861-e58dfe146fdd".equals(function_uuid)) { //获取单位文档所属目录权限 FieldSetEntity fseDirectRight = baseDao.getFieldSetByFilter(CmnConst.PRODUCT_OA_DIRECTORY_RIGHTS, "directory_uuid=?", new Object[] {fseService.getString(CmnConst.DIRECTORY_UUID)}, false); if (fseDirectRight == null) { json.put(CmnConst.IS_PERSSION, 0); }else { boolean succ= BaseUtil.multipleTypeConcat(fseDirectRight.getString(CmnConst.STORAGE_UUID), SpringMVCContextHolder.getCurrentUserId()); if (!succ) { json.put(CmnConst.IS_PERSSION, 0); } } } json.put(CmnConst.SERVICE_UUID, fseService.getString(CoreConst.UUID)); json.put(CmnConst.DATE_TIME, fseService.getString(fseConfig.getString(CmnConst.TIME_FIELD))); json.put(CmnConst.TITLE, fseService.getString(fseConfig.getString(CmnConst.TITLE_FIELD))); } json.put(CoreConst.FUNCTION_NAME, fseConfig.getString(CoreConst.FUNCTION_NAME)); json.put(CoreConst.CREATED_BY, fseAttachment.getString(CoreConst.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(); } }