| | |
| | | import com.product.common.lang.StringUtils; |
| | | import com.product.core.config.CoreConst; |
| | | import com.product.core.dao.BaseDao; |
| | | import com.product.core.entity.DataTableEntity; |
| | | import com.product.core.entity.FieldSetEntity; |
| | | import com.product.core.permission.PermissionService; |
| | | import com.product.core.spring.context.SpringMVCContextHolder; |
| | |
| | | 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.ParseException; |
| | | import org.apache.lucene.queryparser.classic.QueryParser; |
| | | import org.apache.lucene.search.*; |
| | | import org.apache.lucene.search.highlight.Fragmenter; |
| | |
| | | |
| | | import java.io.File; |
| | | import java.io.IOException; |
| | | import java.text.ParseException; |
| | | import java.util.ArrayList; |
| | | import java.util.List; |
| | | |
| | |
| | | @Autowired |
| | | private SearcherManager searcherManager; |
| | | |
| | | |
| | | /** |
| | | * 创建索引 |
| | | * |
| | | * @param fse |
| | | * @throws IOException |
| | | */ |
| | |
| | | |
| | | //获取全文检索配置 |
| | | FieldSetEntity fseConfig=baseDao.getFieldSetEntityByFilter(CmnConst.PRODUCT_SYS_DOCUMENT_SEARCH, "function_uuid=?", new Object[] {function_uuid}, false); |
| | | if (fseConfig!=null) { |
| | | if (fseConfig == null) |
| | | return; |
| | | String table_uuid=fseConfig.getString(CmnConst.TABLE_NAME); |
| | | |
| | | //获取缓存表配置 |
| | | FieldSetEntity fseTable=baseDao.getFieldSetEntity(CoreConst.PRODUCT_SYS_DATAMODEL_TABLE, table_uuid, false); |
| | | if (fseTable!=null) { |
| | | if (fseTable == null) |
| | | return; |
| | | |
| | | //获取附件uuids |
| | | String attachments=fse.getString(CmnConst.ATTACHMENT_UUID); |
| | | if (!StringUtils.isEmpty(attachments)) { |
| | | if (StringUtils.isEmpty(attachments)) |
| | | return; |
| | | |
| | | //遍历获取附件信息 |
| | | String [] attachment=attachments.split(","); |
| | | List<Document> 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) { |
| | | if (fseAttachment == null || file == null) |
| | | return; |
| | | //生成索引信息 |
| | | 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 StoredField(CoreConst.FUNCTION_UUID, function_uuid)); // 功能UUID |
| | | doc.add(new StoredField(CmnConst.UPLOAD_USER, fseAttachment.getString(CoreConst.CREATED_BY))); // 上传人 |
| | | doc.add(new LongPoint(CmnConst.UPLOAD_DATE, fseAttachment.getDate(CoreConst.CREATED_UTC_DATETIME).getTime())); // 上传时间 |
| | | 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)); //文件内内容 |
| | | doc.add(new TextField(CmnConst.FILE_CONTENT, FileUtils.FileToString(file), Field.Store.YES)); // 文件内容 |
| | | docs.add(doc); |
| | | } |
| | | } |
| | | } |
| | | //写入索引 |
| | | try { |
| | |
| | | indexWriter.commit(); |
| | | } catch (IOException e) { |
| | | e.printStackTrace(); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } finally { |
| | | file.delete(); |
| | | } |
| | | |
| | | } |
| | | |
| | | /** |
| | | * 文档检索 |
| | | * |
| | | * @param fse |
| | | * @return |
| | | * @throws Exception |
| | | * @throws ParseException |
| | | */ |
| | | public JSONObject searchProduct(FieldSetEntity fse) throws Exception, ParseException { |
| | | public JSONObject searchProduct(FieldSetEntity fse) throws Exception { |
| | | // 刷新IndexSearcher实例 |
| | | searcherManager.maybeRefresh(); |
| | | IndexSearcher indexSearcher = searcherManager.acquire(); |
| | | |
| | | // 获取安全的IndexSearcher实例 |
| | | IndexSearcher indexSearcher = null; |
| | | //文档信息汇总 |
| | | List<JSONObject> jsonTotal=new ArrayList<>(); |
| | | JSONObject jsonReturn=new JSONObject(); |
| | | Long totalCount = 0L; |
| | | try { |
| | | |
| | | // 模糊匹配,匹配词 |
| | | 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); |
| | | indexSearcher = searcherManager.acquire(); |
| | | |
| | | //高亮格式 |
| | | 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); |
| | | // 获取条件查询结果 |
| | | Query finalQuery = searchFilterParse(fse); |
| | | |
| | | // 获取高亮匹配器 |
| | | Highlighter highlighter = highlighterParse(finalQuery); |
| | | |
| | | |
| | | //分页查询文档 |
| | | TopDocs topDocs = searchByPage(fse.getInteger(CoreConst.CPAGE), fse.getInteger(CoreConst.PAGESIZE), indexSearcher, query); |
| | | |
| | | TopDocs topDocs = searchByPage(fse.getInteger(CoreConst.CPAGE), fse.getInteger(CoreConst.PAGESIZE), |
| | | indexSearcher, finalQuery); |
| | | // 获取检索命中项,总命中数 |
| | | ScoreDoc[] hits = topDocs.scoreDocs; |
| | | totalCount = topDocs.totalHits.value; |
| | | for (int i = 0; i < hits.length; i++) { |
| | | // 获取检索命中的文档信息 |
| | | Document doc = indexSearcher.doc(hits[i].doc); |
| | | String fileUUID = doc.get(CoreConst.UUID); |
| | | String functionUUID = doc.get(CoreConst.FUNCTION_UUID); |
| | | String fileName = doc.get(CmnConst.FILE_NAME); |
| | | String fileContent = doc.get(CmnConst.FILE_CONTENT); |
| | | JSONObject json=new JSONObject(); |
| | | if (!StringUtils.isEmpty(doc.get(CoreConst.FUNCTION_UUID))) { |
| | | getConfig(json, doc.get(CoreConst.FUNCTION_UUID), doc.get(CoreConst.UUID)); |
| | | if (!StringUtils.isEmpty(functionUUID)) { |
| | | getConfig(json, functionUUID, fileUUID); |
| | | } |
| | | 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)); |
| | | // 文件名增加高亮显示 |
| | | String file_name = highlighter.getBestFragment(new SmartChineseAnalyzer(), CmnConst.FILE_NAME, |
| | | CmnConst.FILE_NAME); |
| | | if (StringUtils.isEmpty(file_name)) { |
| | | file_name=doc.get(CmnConst.FILE_NAME); |
| | | file_name = fileName; |
| | | } |
| | | String file_content=highlighter.getBestFragment(new SmartChineseAnalyzer(), CmnConst.FILE_CONTENT,doc.get(CmnConst.FILE_CONTENT)); |
| | | // 文件内容增加高亮显示 |
| | | String file_content = highlighter.getBestFragment(new SmartChineseAnalyzer(), CmnConst.FILE_CONTENT, |
| | | fileContent); |
| | | if (StringUtils.isEmpty(file_content)) { |
| | | file_content=doc.get(CmnConst.FILE_CONTENT); |
| | | file_content = fileContent; |
| | | } |
| | | json.put("file_uuid", fileUUID); |
| | | json.put("function_uuid", functionUUID); |
| | | json.put(CmnConst.FILE_NAME, file_name); |
| | | json.put(CmnConst.FILE_CONTENT, file_content); |
| | | jsonTotal.add(json); |
| | | } |
| | | |
| | | jsonReturn.put(CmnConst.TOTALCOUNT, topDocs.totalHits.value); |
| | | } finally { |
| | | // 关闭实例资源 |
| | | searcherManager.release(indexSearcher); |
| | | } |
| | | |
| | | JSONObject jsonReturn = new JSONObject(); |
| | | getFileInfo(jsonTotal); |
| | | jsonReturn.put(CmnConst.TOTALCOUNT, totalCount); |
| | | jsonReturn.put(CmnConst.DATA, jsonTotal); |
| | | return jsonReturn; |
| | | } |
| | | |
| | | /** |
| | | * 解析查询条件 |
| | | * @param fse |
| | | * @return |
| | | * @throws ParseException |
| | | */ |
| | | public Query searchFilterParse(FieldSetEntity fse) throws ParseException { |
| | | // 上传人 |
| | | String uploadUser = fse.getString("upload_user"); |
| | | String startDate = fse.getString("start_date"); |
| | | String endDate = fse.getString("end_date"); |
| | | String searchKey = fse.getString(CmnConst.SEARCH_KEY); |
| | | |
| | | // 创建查询条件 |
| | | BooleanQuery.Builder boolQuery = new BooleanQuery.Builder(); |
| | | |
| | | // 上传人过滤 |
| | | if (!BaseUtil.strIsNull(uploadUser)) { |
| | | Query uploaderQuery = new TermQuery(new Term("upload_user", uploadUser)); |
| | | boolQuery.add(uploaderQuery, BooleanClause.Occur.MUST); |
| | | } |
| | | // 上传时间过滤 |
| | | if (!BaseUtil.strIsNull(startDate) || !BaseUtil.strIsNull(endDate)) { |
| | | Long longStartDate = Long.MIN_VALUE; |
| | | Long longEndData = Long.MAX_VALUE; |
| | | if (!BaseUtil.strIsNull(startDate)) { |
| | | longStartDate = fse.getDate("start_date").getTime(); |
| | | } |
| | | if (!BaseUtil.strIsNull(endDate)) { |
| | | longEndData = fse.getDate("end_date").getTime(); |
| | | } |
| | | Query timeRangeQuery = LongPoint.newRangeQuery("upload_date", longStartDate, longEndData); |
| | | boolQuery.add(timeRangeQuery, BooleanClause.Occur.MUST); |
| | | } |
| | | |
| | | // 关键词过滤 |
| | | if (!BaseUtil.strIsNull(searchKey)) { |
| | | QueryParser queryParser = new MultiFieldQueryParser( |
| | | new String[] { CmnConst.FILE_NAME, CmnConst.FILE_CONTENT }, new SmartChineseAnalyzer()); |
| | | Query query = queryParser.parse(searchKey); |
| | | boolQuery.add(query, BooleanClause.Occur.MUST); |
| | | } |
| | | return boolQuery.build(); |
| | | } |
| | | |
| | | /** |
| | | * 查询文件高亮匹配器 |
| | | * @param finalQuery |
| | | * @return |
| | | */ |
| | | public Highlighter highlighterParse(Query finalQuery) { |
| | | // 高亮格式 |
| | | SimpleHTMLFormatter simpleHTMLFormatter = new SimpleHTMLFormatter(CmnConst.HIGHLIGHT_BEFORE, |
| | | CmnConst.HIGHLIGHT_AFTER); |
| | | // 高亮匹配器 |
| | | Highlighter highlighter = new Highlighter(simpleHTMLFormatter, new QueryScorer(finalQuery)); |
| | | Fragmenter fragmenter = new SimpleFragmenter(100); |
| | | highlighter.setTextFragmenter(fragmenter); |
| | | return highlighter; |
| | | } |
| | | |
| | | |
| | | public void getFileInfo(List<JSONObject> listJsonFile) { |
| | | StringBuilder sql = new StringBuilder(); |
| | | for (int i = 0; i < listJsonFile.size(); i++) { |
| | | JSONObject jsonFile = listJsonFile.get(i); |
| | | if (i > 0) { |
| | | sql.append("UNION ALL \n"); |
| | | } |
| | | sql.append("SELECT \n"); |
| | | sql.append(" A.uuid,A.attachment_data_table,A.attachment_data_field,D.user_name AS upload_user,A.created_utc_datetime AS upload_date, \n"); |
| | | sql.append(" B.org_fields,B.user_fields,B.title_field,B.time_field \n"); |
| | | sql.append("FROM product_sys_attachments A \n"); |
| | | sql.append("LEFT JOIN product_sys_document_search B ON B.table_name = A.attachment_data_table \n"); |
| | | sql.append("LEFT JOIN product_sys_functions C ON C.uuid = B.function_uuid \n"); |
| | | sql.append("LEFT JOIN product_sys_users D ON D.user_id = A.created_by \n"); |
| | | sql.append("WHERE A.uuid = '").append(jsonFile.get("file_uuid")).append("' \n"); |
| | | } |
| | | DataTableEntity dtConfig = baseDao.listTable(sql.toString(), new Object[] {}); |
| | | if (!BaseUtil.dataTableIsEmpty(dtConfig)) { |
| | | StringBuilder sqlService = new StringBuilder(); |
| | | for (int i = 0; i < dtConfig.getRows(); i++) { |
| | | FieldSetEntity fseConfig = dtConfig.getFieldSetEntity(i); |
| | | if (i > 0) { |
| | | sqlService.append("UNION ALL \n"); |
| | | } |
| | | sqlService.append("SELECT \n"); |
| | | sqlService.append(" A.uuid, \n"); |
| | | sqlService.append(" B.uuid AS service_uuid, \n"); |
| | | sqlService.append(" A.upload_user, A.upload_date, \n"); |
| | | sqlService.append(" ").append(fseConfig.getString(CmnConst.TITLE_FIELD)).append(" AS service_title, \n"); |
| | | sqlService.append(" ").append(fseConfig.getString(CmnConst.TIME_FIELD)).append(" AS service_time \n"); |
| | | sqlService.append("FROM ( \n"); |
| | | sqlService.append(" SELECT \n"); |
| | | sqlService.append(" '").append(fseConfig.getString(CoreConst.UUID)).append("' AS uuid, \n"); |
| | | sqlService.append(" '").append(fseConfig.getString(CmnConst.UPLOAD_USER)).append("' AS upload_user, \n"); |
| | | sqlService.append(" '").append(fseConfig.getString(CmnConst.UPLOAD_DATE)).append("' AS upload_date \n"); |
| | | sqlService.append(") A \n"); |
| | | sqlService.append("LEFT JOIN ").append(fseConfig.getString("attachment_data_table")).append(" B \n"); |
| | | sqlService.append("ON B.").append(fseConfig.getString(CmnConst.ATTACHMENT_DATA_FIELD)).append(" LIKE '%").append(fseConfig.getUUID()).append("%' \n"); |
| | | } |
| | | DataTableEntity dtService = baseDao.listTable(sqlService.toString(), new Object[] {}); |
| | | } |
| | | } |
| | | |
| | | /** |
| | |
| | | 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=?"); |
| | | searchConfigSql.append("SELECT \n"); |
| | | searchConfigSql.append(" A.uuid,A.function_uuid,A.function_button_uuid,A.table_name, \n"); |
| | | searchConfigSql.append(" A.attachment_file,A.org_fields,A.user_fields,title_field,time_field, \n"); |
| | | searchConfigSql.append(" B.function_name,C.button_name \n"); |
| | | searchConfigSql.append("FROM product_sys_document_search A \n"); |
| | | searchConfigSql.append("LEFT JOIN product_sys_functions B ON A.function_uuid = B.uuid \n"); |
| | | searchConfigSql.append("LEFT JOIN product_sys_function_buttons C ON A.function_button_uuid = C.uuid \n"); |
| | | searchConfigSql.append("WHERE A.function_uuid=?"); |
| | | |
| | | //获取文档检索配置 |
| | | FieldSetEntity fseConfig = baseDao.getFieldSetBySQL(searchConfigSql.toString(), new Object[] {function_uuid}, false); |
| | | // 获取文档检索配置(功能,跳转按钮) |
| | | FieldSetEntity fseConfig = baseDao.getFieldSetEntityBySQL(searchConfigSql.toString(), new Object[] { function_uuid }, |
| | | false); |
| | | if (fseConfig!=null) { |
| | | |
| | | //获取跳转按钮 并 判断跳转权限 |
| | |
| | | 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)); |
| | | filter.append(permissionService |
| | | .getDataFilter(fseAttachment.getString(CmnConst.ATTACHMENT_DATA_TABLE), user_fields)); |
| | | } |
| | | }else { |
| | | if (StringUtils.isEmpty(user_fields)) { |
| | |
| | | filter.append(permissionService.getDataFilter(org_fields)); |
| | | }else { |
| | | filter.append(" AND "); |
| | | filter.append(permissionService.getDataFilter(fseAttachment.getString(CmnConst.ATTACHMENT_DATA_TABLE), user_fields, org_fields)); |
| | | 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); |
| | | 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); |
| | | 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); |
| | |
| | | |
| | | //判断是否为文档管理功能,并处理单位文档和个人文档权限 |
| | | if("e4fa2c88-88a4-4ef4-9020-ebbe0440b4cf".equals(function_uuid)) { |
| | | if(!SpringMVCContextHolder.getCurrentUserId().equals(fseService.getString(CoreConst.CREATED_BY))) { |
| | | 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); |
| | | 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()); |
| | | boolean succ = BaseUtil.multipleTypeConcat(fseDirectRight.getString(CmnConst.STORAGE_UUID), |
| | | SpringMVCContextHolder.getCurrentUserId()); |
| | | if (!succ) { |
| | | json.put(CmnConst.IS_PERSSION, 0); |
| | | } |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 文件检索查询分页 |
| | | * |
| | | * @param cpage 当前页 |
| | | * @param pagesize 每页大小 |
| | | * @param searcher 查询器 |
| | |
| | | |
| | | /** |
| | | * 根据附件uuid删除索引 |
| | | * |
| | | * @param uuid |
| | | * @throws IOException |
| | | */ |