diff --git a/shandan-browser/src/main/java/com/keyware/shandan/browser/controller/SearchController.java b/shandan-browser/src/main/java/com/keyware/shandan/browser/controller/SearchController.java index fd192a3..e632efd 100644 --- a/shandan-browser/src/main/java/com/keyware/shandan/browser/controller/SearchController.java +++ b/shandan-browser/src/main/java/com/keyware/shandan/browser/controller/SearchController.java @@ -8,6 +8,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.keyware.shandan.bianmu.entity.DirectoryResource; import com.keyware.shandan.bianmu.entity.MetadataBasicVo; import com.keyware.shandan.bianmu.service.MetadataService; +import com.keyware.shandan.browser.entity.FullSearchParam; import com.keyware.shandan.browser.entity.PageVo; import com.keyware.shandan.browser.entity.SearchConditionVo; import com.keyware.shandan.browser.entity.SearchResultSort; @@ -139,10 +140,10 @@ public class SearchController { */ @AppLog(operate = "文件全文检索查询") @GetMapping("/full/file") - public Result searchFile(PageVo page, String search, String metaId, SearchResultSort sort) { + public Result searchFile(FullSearchParam param) { try { - return Result.of(fileSearchService.searchFile(page, search, metaId, sort)); + return Result.of(fileSearchService.searchFile(param)); } catch (IOException e) { e.printStackTrace(); return Result.of(null, false, "Elasticsearch 请求异常"); diff --git a/shandan-browser/src/main/java/com/keyware/shandan/browser/entity/FullSearchParam.java b/shandan-browser/src/main/java/com/keyware/shandan/browser/entity/FullSearchParam.java new file mode 100644 index 0000000..f6ae28f --- /dev/null +++ b/shandan-browser/src/main/java/com/keyware/shandan/browser/entity/FullSearchParam.java @@ -0,0 +1,31 @@ +package com.keyware.shandan.browser.entity; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 全文检索查询参数 + * + * @author GuoXin + * @date 2023/9/9 + */ +@Data +@EqualsAndHashCode(callSuper = true) +public class FullSearchParam extends SearchResultSort { + /** + * 搜索的文本 + */ + String search; + /** + * 搜索类型,是否为匹配文本片段 + */ + String searchType; + /** + * 资源ID + */ + String metaId; + /** + * 要查询的字段集合,以英文逗号字符拼接 + */ + String searchFields; +} diff --git a/shandan-browser/src/main/java/com/keyware/shandan/browser/entity/SearchResultSort.java b/shandan-browser/src/main/java/com/keyware/shandan/browser/entity/SearchResultSort.java index c3b7911..46e9e83 100644 --- a/shandan-browser/src/main/java/com/keyware/shandan/browser/entity/SearchResultSort.java +++ b/shandan-browser/src/main/java/com/keyware/shandan/browser/entity/SearchResultSort.java @@ -15,7 +15,7 @@ import lombok.Setter; */ @Getter @Setter -public class SearchResultSort { +public class SearchResultSort extends PageVo { //排序字段 private String field; //排序方式 diff --git a/shandan-browser/src/main/java/com/keyware/shandan/browser/service/FileSearchService.java b/shandan-browser/src/main/java/com/keyware/shandan/browser/service/FileSearchService.java index 3b51885..8fa5f6f 100644 --- a/shandan-browser/src/main/java/com/keyware/shandan/browser/service/FileSearchService.java +++ b/shandan-browser/src/main/java/com/keyware/shandan/browser/service/FileSearchService.java @@ -4,8 +4,8 @@ import cn.hutool.core.util.ReflectUtil; import com.keyware.shandan.bianmu.entity.DirectoryVo; import com.keyware.shandan.bianmu.enums.ReviewStatus; import com.keyware.shandan.bianmu.service.DirectoryService; +import com.keyware.shandan.browser.entity.FullSearchParam; import com.keyware.shandan.browser.entity.PageVo; -import com.keyware.shandan.browser.entity.SearchResultSort; import com.keyware.shandan.common.constants.DirConstant; import com.keyware.shandan.common.util.StreamUtil; import com.keyware.shandan.common.util.StringUtils; @@ -17,20 +17,18 @@ import org.elasticsearch.client.RequestOptions; import org.elasticsearch.client.Requests; import org.elasticsearch.client.RestHighLevelClient; import org.elasticsearch.index.query.BoolQueryBuilder; -import org.elasticsearch.index.query.QueryBuilder; import org.elasticsearch.index.query.QueryBuilders; import org.elasticsearch.search.builder.SearchSourceBuilder; import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder; -import org.elasticsearch.search.sort.FieldSortBuilder; import org.elasticsearch.search.sort.SortOrder; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.elasticsearch.annotations.FieldType; import org.springframework.stereotype.Service; import java.io.IOException; -import java.lang.annotation.Annotation; import java.lang.reflect.Field; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; /** @@ -48,10 +46,15 @@ public class FileSearchService { @Autowired private DirectoryService directoryService; - public PageVo searchFile(PageVo page, String text, String metaId, SearchResultSort sort) throws IOException { + public PageVo searchFile(FullSearchParam param) throws IOException { + SearchRequest request = Requests.searchRequest("shandan"); SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); - searchSourceBuilder.from(page.getPage() * page.getSize() - page.getSize()).size(page.getSize()); + searchSourceBuilder.from(param.getPage() * param.getSize() - param.getSize()).size(param.getSize()); + + String metaId = param.getMetaId(); + String text = param.getSearch(); + String[] searchFields = param.getSearchFields().split(","); BoolQueryBuilder builder = QueryBuilders.boolQuery(); if (!DirConstant.DIR_ROOT_ID.equals(metaId)) { @@ -61,19 +64,19 @@ public class FileSearchService { builder.must(QueryBuilders.termsQuery("entityId", ids)); } if (StringUtils.isNotBlank(text)) { - BoolQueryBuilder should = QueryBuilders.boolQuery(); - should.should(QueryBuilders.matchQuery("fileName", text)); - should.should(QueryBuilders.matchQuery("entryStaff", text)); - should.should(QueryBuilders.matchQuery("equipmentModel", text)); - should.should(QueryBuilders.matchQuery("source", text)); - should.should(QueryBuilders.matchQuery("taskCode", text)); - should.should(QueryBuilders.matchQuery("taskNature", text)); - should.should(QueryBuilders.matchQuery("troopCode", text)); - should.should(QueryBuilders.matchQuery("targetNumber", text)); - should.should(QueryBuilders.matchQuery("missileNumber", text)); - should.should(QueryBuilders.matchQuery("remark", text)); - should.should(QueryBuilders.matchQuery("text", text)); - builder.must(should); + BoolQueryBuilder boolQuery = QueryBuilders.boolQuery(); + String[] includesCol = {"fileName", "entryStaff", "equipmentModel", "source", "taskCode", "taskNature", "troopCode", "targetNumber", "missileNumber", "themeTask", "remark", "text"}; + + for (String colName : searchFields) { + if (Arrays.asList(includesCol).contains(colName)) { + if ("phrase".equals(param.getSearchType())) { + boolQuery.should(QueryBuilders.matchPhraseQuery(colName, text)); + } else { + boolQuery.should(QueryBuilders.matchQuery(colName, text)); + } + } + } + builder.must(boolQuery); } // 高亮显示设置 @@ -87,23 +90,23 @@ public class FileSearchService { searchSourceBuilder.query(builder).highlighter(highlightBuilder); // 设置排序 - if (!sort.isEmpty()) { - String sortField = sort.getField(); + if (!param.isEmpty()) { + String sortField = param.getField(); // 使用反射获取文件实体类中字段上的注解设置的字段类型 Field field = ReflectUtil.getField(SysFile.class, sortField); if (field != null) { org.springframework.data.elasticsearch.annotations.Field fieldAnno = field.getAnnotation(org.springframework.data.elasticsearch.annotations.Field.class); - if(fieldAnno.type() != FieldType.Text + if (fieldAnno.type() != FieldType.Text && fieldAnno.type() != FieldType.Object && fieldAnno.type() != FieldType.Auto && fieldAnno.type() != FieldType.Nested && fieldAnno.type() != FieldType.Ip - && fieldAnno.type() != FieldType.Attachment){ - if(fieldAnno.type() == FieldType.Keyword){ + && fieldAnno.type() != FieldType.Attachment) { + if (fieldAnno.type() == FieldType.Keyword) { sortField = sortField.concat(".keyword"); } - searchSourceBuilder.sort(sortField, SortOrder.fromString(sort.getSort())); - }else { + searchSourceBuilder.sort(sortField, SortOrder.fromString(param.getSort())); + } else { log.error("不支持的排序类型:{}:{}", sortField, fieldAnno.type()); } } @@ -113,7 +116,7 @@ public class FileSearchService { // 设置排序 SearchResponse response = esClient.search(request, RequestOptions.DEFAULT); - return PageVo.ofSearchHits(response.getHits(), page); + return PageVo.ofSearchHits(response.getHits(), param); } private List getChildrenByDirId(String dirId) { diff --git a/shandan-browser/src/main/resources/static/js/browser.js b/shandan-browser/src/main/resources/static/js/browser.js index 3315115..51a819a 100644 --- a/shandan-browser/src/main/resources/static/js/browser.js +++ b/shandan-browser/src/main/resources/static/js/browser.js @@ -152,7 +152,7 @@ layui.use(['layer', 'listPage', 'globalTree', 'gtable', 'form', 'element', 'drop if (_table.where.conditions && _table.where.conditions.length > 0) { let formVal = form.val('search-form'); formVal = Object.assign(formVal, whereConditionToFormValue(_table.where)); - if(preciseQuery === 'eq'){ + if (preciseQuery === 'eq') { formVal['preciseQuery'] = 'eq'; } form.val('search-form', formVal); @@ -211,45 +211,6 @@ layui.use(['layer', 'listPage', 'globalTree', 'gtable', 'form', 'element', 'drop metaListTable.addTableRowEvent('theadSet1', () => tHeadSetLayer.show(resourceTableId)) } - function initFileSearchTable(id) { - const theadConfig = THeadSetLayer.filterConfigData(fileTableId) - dirFileTable = listPage.init({ - table: { - id: 'dirFileTable', - toolbar: '#fileTableToolBar', - searchInput: 'fileSearchKeyInput', - searchFieldNames: 'search', - url: `${ctx}/search/full/file?metaId=${id}`, - height: 'full-110', - request: {pageName: 'page', limitName: 'size'}, - defaultToolbar: [{title: '列表配置', layEvent: 'theadSet2', icon: 'layui-icon-cols'}], - autoSort: false, - limit: 30, - method: 'get', - minWidth: 80, - cols: THeadSetLayer.convertColumns(theadConfig, 'dirFileTable') - }, - }); - - dirFileTable.gtable.on('sort', function (data) { - const {field, type} = data; - let sort = type; - if (!sort || sort === 'null') { - sort = undefined; - } - dirFileTable.table.where.field = field.trim(); - dirFileTable.table.where.sort = sort; - dirFileTable.reloadTable({table: dirFileTable.table}) - }) - - // 查看按钮监听 - dirFileTable.addTableRowEvent('details-file', function (obj) { - openMaxLayerWithURL(`${ctx}/sys/file/view?fileId=${obj.id}`) - }) - - dirFileTable.addTableRowEvent('theadSet2', () => tHeadSetLayer.show(fileTableId)) - } - /** * 搜索条件模块初始化 */ @@ -330,7 +291,7 @@ layui.use(['layer', 'listPage', 'globalTree', 'gtable', 'form', 'element', 'drop setSearchKeyCondition(value, preciseQuery === 'eq' ? 'eq' : 'like'); }) - function setSearchKeyCondition(value, logic){ + function setSearchKeyCondition(value, logic) { let where = metaListTable.where || {}; let conditions = where.conditions || []; conditions = conditions.filter(item => item.fieldName !== 'metadataName') @@ -480,6 +441,60 @@ layui.use(['layer', 'listPage', 'globalTree', 'gtable', 'form', 'element', 'drop closeBtn: 1 }); } + + /** + * 初始化文件全文检索查询列表 + * @param id 目录ID + */ + function initFileSearchTable(id) { + const theadConfig = THeadSetLayer.filterConfigData(fileTableId); + let queryType = ''; + dirFileTable = listPage.init({ + table: { + id: 'dirFileTable', + toolbar: '#fileTableToolBar', + searchInput: 'fileSearchKeyInput', + searchFieldNames: 'search', + url: `${ctx}/search/full/file?metaId=${id}`, + height: 'full-110', + where: {searchFields: THeadSetLayer.filterConfigData(fileTableId).filter(conf=>conf.isShow).map(conf => conf.colName).join(',')}, + request: {pageName: 'page', limitName: 'size'}, + defaultToolbar: [{title: '列表配置', layEvent: 'theadSet2', icon: 'layui-icon-cols'}], + autoSort: false, + limit: 30, + method: 'get', + minWidth: 80, + cols: THeadSetLayer.convertColumns(theadConfig, 'dirFileTable'), + done: () => { + form.val('full-search-form', {queryType}); + } + }, + }); + + form.on('checkbox(query-type)', function ({value, othis}) { + queryType = othis.hasClass('layui-form-checked') ? value : ''; + dirFileTable.table.where.searchType = queryType; + }); + + dirFileTable.gtable.on('sort', function (data) { + const {field, type} = data; + let sort = type; + if (!sort || sort === 'null') { + sort = undefined; + } + dirFileTable.table.where.field = field.trim(); + dirFileTable.table.where.sort = sort; + dirFileTable.reloadTable({table: dirFileTable.table}) + }) + + // 查看按钮监听 + dirFileTable.addTableRowEvent('details-file', function (obj) { + openMaxLayerWithURL(`${ctx}/sys/file/view?fileId=${obj.id}`) + }) + + dirFileTable.addTableRowEvent('theadSet2', () => tHeadSetLayer.show(fileTableId)) + } + }) /** @@ -521,7 +536,7 @@ class THeadSetLayer { const {gtable, form, id} = this; gtable.init({ id, - data: this.filterConfigData(tableId), + data: THeadSetLayer.filterConfigData(tableId), method: 'get', toolbar: false, height: 'full', diff --git a/shandan-browser/src/main/resources/view/browser.html b/shandan-browser/src/main/resources/view/browser.html index 3509ffe..34c7fa1 100644 --- a/shandan-browser/src/main/resources/view/browser.html +++ b/shandan-browser/src/main/resources/view/browser.html @@ -214,8 +214,9 @@
当前位置: