Elastic Search搜索实例
程序员文章站
2022-07-10 15:02:40
...
要从现在的公司离职了。记录一下自己针对我们的自己需求所做的搜索。
基于Spring data,ES 2.X版本的
基于Spring data,ES 2.X版本的
package com.xxxx.cms.elasticsearch.domain; import java.util.Calendar; import org.apache.commons.lang3.StringUtils; import org.jsoup.Jsoup; import org.springframework.data.annotation.Id; import org.springframework.data.elasticsearch.annotations.Document; import org.springframework.data.elasticsearch.annotations.Field; import org.springframework.data.elasticsearch.annotations.FieldIndex; import org.springframework.data.elasticsearch.annotations.FieldType; import com.xxxx.cms.content.common.domain.CmsContent; @Document(indexName = "cms", type = "contentIndex") public class ContentIndex { /** 主键ID */ @Id private Long id; /** 标题 */ @Field(store = true, type = FieldType.String, analyzer = "ik") private String title; /** 标签 */ @Field(store = true, type = FieldType.String, analyzer = "ik") private String[] tags; /** 相关股票 */ @Field(store = true, type = FieldType.String, analyzer = "ik") private String[] relatedStocks; /** 摘要 */ @Field(store = true, type = FieldType.String, analyzer = "ik") private String description; /** 内容 */ @Field(store = false, type = FieldType.String, analyzer = "ik") private String contentTxt; // 状态值 @Field(store = true, type = FieldType.Integer, index = FieldIndex.not_analyzed) private Integer status; @Field(store = true, type = FieldType.Integer, index = FieldIndex.not_analyzed) private Long channelId; // 栏目ID @Field(store = true, type = FieldType.Integer, index = FieldIndex.not_analyzed) private Integer typeId; @Field(store = true, type = FieldType.Long, index = FieldIndex.not_analyzed) private Long flagBit; @Field(store = true, type = FieldType.Integer, index = FieldIndex.not_analyzed) private Long topicId; /** 创建时间 */ @Field(store = true, type = FieldType.Date, index = FieldIndex.not_analyzed) private Calendar createdDate; /** 发布时间 */ @Field(store = true, type = FieldType.Date, index = FieldIndex.not_analyzed) private Calendar releasedDate; public ContentIndex() { } public ContentIndex(Long id, Integer status, String title, String[] tags, String[] relatedStocks, String description, String contentTxt, Long channelId, Integer typeId, Long flagBit, Long topicId, Calendar createdDate, Calendar releasedDate) { this.id = id; this.status = status; this.title = title; this.tags = tags; this.relatedStocks = relatedStocks; this.channelId = channelId; this.typeId = typeId; this.flagBit = flagBit; this.topicId = topicId; this.createdDate = createdDate; this.releasedDate = releasedDate; this.contentTxt = contentTxt; if (StringUtils.isBlank(description) && StringUtils.isNotEmpty(contentTxt)) { String contTxt = Jsoup.parse(contentTxt).text(); this.description = contTxt.length() > 200 ? contTxt.substring(0, 200) : contTxt; } else { this.description = description; } } public ContentIndex(CmsContent cmsContent) { this.id = cmsContent.getId(); this.status = cmsContent.getStatus().getIndex(); this.title = cmsContent.getTitle(); this.tags = cmsContent.getESTags(); this.relatedStocks = cmsContent.getESRelatedStocks(); this.channelId = cmsContent.getChannelId(); this.typeId = cmsContent.getTypeId(); this.flagBit = cmsContent.getFlagBit(); this.topicId = cmsContent.getTopicId(); this.createdDate = cmsContent.getCreatedDate(); this.releasedDate = cmsContent.getReleasedDate(); this.contentTxt = cmsContent.getContentTxt(); if (StringUtils.isBlank(cmsContent.getDescription()) && StringUtils.isNotEmpty(contentTxt)) { String contTxt = Jsoup.parse(contentTxt).text(); this.description = contTxt.length() > 200 ? contTxt.substring(0, 200) : contTxt; } else { this.description = cmsContent.getDescription(); } } public Long getId() { return id; } public void setId(Long id) { this.id = id; } public Integer getStatus() { return status; } public void setStatus(Integer status) { this.status = status; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String[] getTags() { return tags; } public void setTags(String[] tags) { this.tags = tags; } public String[] getRelatedStocks() { return relatedStocks; } public void setRelatedStocks(String[] relatedStocks) { this.relatedStocks = relatedStocks; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public String getContentTxt() { return contentTxt; } public void setContentTxt(String contentTxt) { this.contentTxt = contentTxt; } public Long getChannelId() { return channelId; } public void setChannelId(Long channelId) { this.channelId = channelId; } public Integer getTypeId() { return typeId; } public void setTypeId(Integer typeId) { this.typeId = typeId; } public Long getFlagBit() { return flagBit; } public void setFlagBit(Long flagBit) { this.flagBit = flagBit; } public Long getTopicId() { return topicId; } public void setTopicId(Long topicId) { this.topicId = topicId; } public Calendar getCreatedDate() { return createdDate; } public void setCreatedDate(Calendar createdDate) { this.createdDate = createdDate; } public Calendar getReleasedDate() { return releasedDate; } public void setReleasedDate(Calendar releasedDate) { this.releasedDate = releasedDate; } }
package com.xxxx.cms.elasticsearch.service.impl; import java.time.Duration; import java.time.LocalDateTime; import java.time.ZoneOffset; import java.util.ArrayList; import java.util.Calendar; import java.util.List; import java.util.Objects; import java.util.stream.Collectors; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.jsoup.Jsoup; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.task.TaskExecutor; import org.springframework.data.elasticsearch.core.ElasticsearchOperations; import org.springframework.stereotype.Service; import com.aicai.appmodel.domain.result.ModelResult; import com.aicai.appmodel.page.DataPage; import com.xxxx.cms.channel.common.domain.CmsChannelDefine; import com.xxxx.cms.channel.common.service.CmsChannelDefineService; import com.xxxx.cms.channel.common.type.ChannelDefineType; import com.xxxx.cms.config.props.EsProps; import com.xxxx.cms.content.common.domain.CmsContent; import com.xxxx.cms.content.common.domain.CmsContentStock; import com.xxxx.cms.content.common.domain.CmsContentTag; import com.xxxx.cms.content.common.domain.CmsContentTxt; import com.xxxx.cms.content.common.type.ContentStatus; import com.xxxx.cms.content.common.vo.CmsContentQueryVo; import com.xxxx.cms.content.manager.CmsContentManager; import com.xxxx.cms.content.manager.CmsContentStockManager; import com.xxxx.cms.content.manager.CmsContentTagManager; import com.xxxx.cms.content.manager.CmsContentTxtManager; import com.xxxx.cms.elasticsearch.common.domain.ContentSearchResult; import com.xxxx.cms.elasticsearch.common.service.ContentIndexReadService; import com.xxxx.cms.elasticsearch.constant.ElasticSearchConstant; import com.xxxx.cms.elasticsearch.domain.ContentIndex; import com.xxxx.cms.elasticsearch.domain.HelpCenterContentIndex; import com.xxxx.cms.elasticsearch.manager.ContentIndexManager; import com.xxxx.cms.elasticsearch.repositories.ContentIndexRepository; import com.xxxx.cms.elasticsearch.repositories.HelpCenterRepository; @Service("contentIndexReadService") public class ContentIndexReadServiceImpl implements ContentIndexReadService, InitializingBean { private Logger logger = LoggerFactory.getLogger(getClass()); @Autowired private ContentIndexManager contentIndexManager; @Autowired private ContentIndexRepository contentIndexRepository; @Autowired private HelpCenterRepository helpCenterRepository; @Autowired private ElasticsearchOperations elasticsearchTemplate; @Autowired private CmsContentStockManager cmsContentStockManager; @Autowired private CmsContentTagManager cmsContentTagManager; @Autowired private CmsContentManager cmsContentManager; @Autowired private CmsContentTxtManager cmsContentTxtManager; @Autowired private CmsChannelDefineService cmsChannelDefineService; @Autowired private TaskExecutor taskExecutor; @Autowired private EsProps esProps; private final int page_size = 1000; @SuppressWarnings("unchecked") @Override public void afterPropertiesSet() throws Exception { if (esProps.isInit() == false) return; boolean delContentIdxFlag = elasticsearchTemplate.deleteIndex(ElasticSearchConstant.CMS_INDEX); logger.warn("ES删除ContentIndex索引:{}", delContentIdxFlag); if (delContentIdxFlag == false) { logger.error("ES删除ContentIndex索引失败,重建索引退出"); return; } boolean createContentIdxFlag = elasticsearchTemplate.createIndex(ElasticSearchConstant.CMS_INDEX); logger.warn("ES创建cms索引:{}", createContentIdxFlag); if (createContentIdxFlag == false) { logger.error("ES删除ContentIndex索引失败,重建索引退出"); return; } boolean contentIndexMappingFlag = elasticsearchTemplate.putMapping(ContentIndex.class); logger.warn("ES创建cms:contentIndex映射:{}", contentIndexMappingFlag); elasticsearchTemplate.getMapping(ElasticSearchConstant.CMS_INDEX, ElasticSearchConstant.CMS_CONTENT_TYPE).entrySet() .forEach(obj -> logger.warn("ES创建ContentIndex索引,映射关系为:{}", obj)); boolean helpCenterIndexMappingFlag = elasticsearchTemplate.putMapping(HelpCenterContentIndex.class); logger.warn("ES创建cms:helpCenterIndex映射:{}", helpCenterIndexMappingFlag); elasticsearchTemplate.getMapping(ElasticSearchConstant.CMS_INDEX, ElasticSearchConstant.CMS_HELP_CENTER_TYPE).entrySet() .forEach(obj -> logger.warn("ES创建helpCenterIndex索引,映射关系为:{}", obj)); indexInit(); helpCenterInit(); } private void indexInit() { taskExecutor.execute(() -> { logger.info("初始化contentIndex开始"); LocalDateTime beginTime = LocalDateTime.now(); contentIndexRepository.deleteAll(); DataPage<CmsContent> dataPage = new DataPage<>(); dataPage.setPageSize(page_size); dataPage.setOrder("ASC"); dataPage.setOrderBy("released_date"); Calendar beginReleasedDate = Calendar.getInstance(); // 只初始化一年内的资讯 beginReleasedDate.setTimeInMillis(LocalDateTime.now().minusYears(1).toInstant(ZoneOffset.ofHours(8)).toEpochMilli()); CmsContentQueryVo queryVo = new CmsContentQueryVo(); queryVo.setStatus(ContentStatus.PUBLISH); for (int i = 1;; i++) { dataPage.setPageNo(1); beginReleasedDate.add(Calendar.SECOND, 1); queryVo.setBeginReleasedDate(beginReleasedDate); DataPage<CmsContent> contentPage = cmsContentManager.queryByVo(dataPage, queryVo); logger.info("create page:{}, pageSize:{}, total:{}", i, contentPage.getPageSize(), contentPage.getTotalCount()); List<CmsContent> contents = contentPage.getDataList(); if (CollectionUtils.isEmpty(contents)) { break; } List<Long> contIdList = contents.stream().map(CmsContent::getId).collect(Collectors.toList()); List<CmsContentTxt> txtList = cmsContentTxtManager.query(contIdList); List<CmsContentStock> stockList = cmsContentStockManager.queryByContentIdList(contIdList); List<CmsContentTag> tagList = cmsContentTagManager.queryByIdList(contIdList); List<ContentIndex> indexs = new ArrayList<>(); for (CmsContent c : contents) { if (CollectionUtils.isNotEmpty(txtList)) { txtList.stream().filter(txt -> txt.getContentId().longValue() == c.getId().longValue()).findAny().ifPresent(txt -> { c.setContentTxt(txt.getTxt()); if (StringUtils.isEmpty(c.getDescription())) { String contTxt = Jsoup.parse(c.getContentTxt()).text(); String txtStr = contTxt.length() > 200 ? contTxt.substring(0, 200) : contTxt; c.setDescription(txtStr); } }); } if (CollectionUtils.isNotEmpty(tagList)) { List<String> tagStrList = tagList.stream().filter(tag -> tag.getContentId().longValue() == c.getId().longValue()) .map(CmsContentTag::getTagName).filter(StringUtils::isNotBlank).collect(Collectors.toList()); if (CollectionUtils.isNotEmpty(tagStrList) && tagStrList.toArray() != null && tagStrList.toArray() instanceof String[]) { c.setESTags((String[]) tagStrList.toArray()); } } if (CollectionUtils.isNotEmpty(stockList)) { List<String> stockStrList = stockList.stream().filter(stock -> stock.getContentId().longValue() == c.getId().longValue()) .map(CmsContentStock::getStockCode).filter(StringUtils::isNotBlank).collect(Collectors.toList()); if (CollectionUtils.isNotEmpty(stockStrList) && stockStrList.toArray() != null && stockStrList.toArray() instanceof String[]) { c.setESRelatedStocks((String[]) stockStrList.toArray()); } } ContentIndex index = new ContentIndex(c); indexs.add(index); } contentIndexRepository.save(indexs); beginReleasedDate = contents.get(contents.size() - 1).getReleasedDate(); } LocalDateTime endTime = LocalDateTime.now(); logger.info("初始化contentIndex结束,共耗时:{} min", String.valueOf(Duration.between(beginTime, endTime).toMinutes())); }); } private void helpCenterInit() { taskExecutor.execute(() -> { logger.info("初始化 help-center 开始"); LocalDateTime beginTime = LocalDateTime.now(); helpCenterRepository.deleteAll(); DataPage<CmsContent> dataPage = new DataPage<>(); dataPage.setPageSize(page_size); dataPage.setOrder("ASC"); dataPage.setOrderBy("released_date"); Calendar beginReleasedDate = Calendar.getInstance(); beginReleasedDate.set(1970, 10, 10, 10, 10, 10); CmsContentQueryVo queryVo = new CmsContentQueryVo(); queryVo.setStatus(ContentStatus.PUBLISH); ModelResult<List<CmsChannelDefine>> modelResult = cmsChannelDefineService .queryLastChildByChannel(ChannelDefineType.NEW_HELP_CENTER.getIndex().longValue()); List<CmsChannelDefine> cmsChannelDefines = modelResult.getModel(); List<Long> ids = new ArrayList<>(); cmsChannelDefines.stream().forEach(p -> { ids.add(p.getId()); }); logger.info("helpCenterInit ids:{}", ids.size()); for (int i = 1; ; i++) { dataPage.setPageNo(1); beginReleasedDate.add(Calendar.SECOND, 1); queryVo.setBeginReleasedDate(beginReleasedDate); queryVo.setChannelIds(ids); DataPage<CmsContent> contentPage = cmsContentManager.queryByVo(dataPage, queryVo); logger.info("helpCenterInit create page:{}, pageSize:{}, total:{}", i, contentPage.getPageSize(), contentPage.getTotalCount()); List<CmsContent> contents = contentPage.getDataList(); if (CollectionUtils.isEmpty(contents)) { break; } List<Long> contIdList = contents.stream() .map(CmsContent::getId) .collect(Collectors.toList()); List<CmsContentTxt> txtList = cmsContentTxtManager.query(contIdList); List<CmsContentStock> stockList = cmsContentStockManager.queryByContentIdList(contIdList); List<CmsContentTag> tagList = cmsContentTagManager.queryByIdList(contIdList); List<HelpCenterContentIndex> indexs = new ArrayList<>(); for(CmsContent c : contents) { if (CollectionUtils.isNotEmpty(txtList)) { txtList.stream() .filter(txt -> txt.getContentId().longValue() == c.getId().longValue()) .findAny() .ifPresent(txt -> { c.setContentTxt(txt.getTxt()); if (StringUtils.isEmpty(c.getDescription())) { String contTxt = Jsoup.parse(c.getContentTxt()).text(); String txtStr = contTxt.length() > 200 ? contTxt.substring(0, 200) : contTxt; c.setDescription(txtStr); } }); } if (CollectionUtils.isNotEmpty(tagList)) { List<String> tagStrList = tagList.stream() .filter(tag -> tag.getContentId().longValue() == c.getId().longValue()) .map(CmsContentTag::getTagName) .filter(StringUtils::isNotBlank) .collect(Collectors.toList()); if (CollectionUtils.isNotEmpty(tagStrList) && tagStrList.toArray() != null && tagStrList.toArray() instanceof String[]) { c.setESTags((String[]) tagStrList.toArray()); } } if (CollectionUtils.isNotEmpty(stockList)) { List<String> stockStrList = stockList.stream() .filter(stock -> stock.getContentId().longValue() == c.getId().longValue()) .map(CmsContentStock::getStockCode) .filter(StringUtils::isNotBlank) .collect(Collectors.toList()); if (CollectionUtils.isNotEmpty(stockStrList) && stockStrList.toArray() != null && stockStrList.toArray() instanceof String[]) { c.setESRelatedStocks((String[])stockStrList.toArray()); } } HelpCenterContentIndex index = new HelpCenterContentIndex(c); indexs.add(index); } helpCenterRepository.save(indexs); beginReleasedDate = contents.get(contents.size() - 1).getReleasedDate(); } LocalDateTime endTime = LocalDateTime.now(); logger.info("初始化helpCenterInit结束,共耗时:{} min", String.valueOf(Duration.between(beginTime, endTime).toMinutes())); }); } @Override public DataPage<ContentSearchResult> searchContentByKeyword(String keyword, List<String> filterField, DataPage<ContentSearchResult> dataPage) { DataPage<ContentSearchResult> reDataPage = contentIndexManager.searchContentByKeyword(keyword, filterField, dataPage); // if (dataPage.getPageNo() < 2) { // List<ContentSearchResult> dataList = dataPage.getDataList(); // if (CollectionUtils.isNotEmpty(dataList)) { // dataList.sort((c1, c2) -> c2.getReleasedDate().compareTo(c1.getReleasedDate())); // } // } return reDataPage; } @Override public List<ContentSearchResult> searchByKeyword(String keyword, int pageSize, int pageNo) { Objects.requireNonNull(keyword); return contentIndexManager.searchByKeyword(keyword, pageSize, pageNo); } @Override public DataPage<ContentSearchResult> searchContentByTags(DataPage<ContentSearchResult> dataPage, Long id, Long channelId, String[] tags) { return contentIndexManager.searchContentByTags(dataPage, id, channelId, tags); } @Override public DataPage<ContentSearchResult> searchContentByKeyword(String keyword, List<String> filterField, DataPage<ContentSearchResult> dataPage, String[] esIndexs, String[] esTypes) { return contentIndexManager.searchContentByKeyword(keyword, filterField, dataPage, esIndexs, esIndexs); } @Override public List<ContentSearchResult> searchByKeyword(String keyword, int pageSize, int pageNo, String[] esIndexs, String[] esTypes) { return contentIndexManager.searchByKeyword(keyword, pageSize, pageNo, esIndexs, esTypes); } @Override public DataPage<ContentSearchResult> searchContentByTags(DataPage<ContentSearchResult> dataPage, Long id, Long channelId, String[] tags, String[] esIndexs, String[] esTypes) { return contentIndexManager.searchContentByTags(dataPage, id, channelId, tags, esIndexs, esTypes); } }
package com.xxxx.cms.elasticsearch.manager.impl; import static org.elasticsearch.index.query.QueryBuilders.boolQuery; import static org.elasticsearch.index.query.QueryBuilders.matchPhraseQuery; import static org.elasticsearch.index.query.QueryBuilders.matchQuery; import static org.elasticsearch.index.query.QueryBuilders.multiMatchQuery; import static org.elasticsearch.index.query.QueryBuilders.rangeQuery; import static org.elasticsearch.index.query.QueryBuilders.termQuery; import static org.elasticsearch.index.query.QueryBuilders.termsQuery; import java.time.Duration; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.ZoneOffset; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.stream.Collectors; import javax.annotation.Resource; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.elasticsearch.action.search.SearchResponse; //import org.elasticsearch.common.base.Strings; import org.elasticsearch.common.text.Text; import org.elasticsearch.index.query.BoolQueryBuilder; //import org.elasticsearch.index.query.FilterBuilders; import org.elasticsearch.index.query.MatchQueryBuilder; import org.elasticsearch.index.query.MultiMatchQueryBuilder.Type; import org.elasticsearch.index.query.QueryBuilders; import org.elasticsearch.search.SearchHit; import org.elasticsearch.search.highlight.HighlightBuilder; import org.elasticsearch.search.highlight.HighlightField; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort.Direction; import org.springframework.data.elasticsearch.core.ElasticsearchOperations; import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder; import org.springframework.data.elasticsearch.core.query.SearchQuery; import org.springframework.stereotype.Repository; import com.xxxx.appmodel.domain.result.ModelResult; import com.xxxx.appmodel.page.DataPage; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.xxxx.cms.channel.common.domain.CmsChannelDefine; import com.xxxx.cms.channel.common.service.CmsChannelDefineService; import com.xxxx.cms.channel.common.type.ChannelDefineType; import com.xxxx.cms.channel.manager.CmsChannelDefineManager; import com.xxxx.cms.config.constant.BaseConstant; import com.xxxx.cms.content.common.domain.CmsContent; import com.xxxx.cms.content.common.domain.CmsContentTag; import com.xxxx.cms.content.common.type.ContentStatus; import com.xxxx.cms.content.common.utils.ContentFlagBitOperUtils; import com.xxxx.cms.content.manager.CmsContentTagManager; import com.xxxx.cms.elasticsearch.common.domain.ContentSearchResult; import com.xxxx.cms.elasticsearch.constant.CacheConstant; import com.xxxx.cms.elasticsearch.constant.ElasticSearchConstant; import com.xxxx.cms.elasticsearch.domain.ContentIndex; import com.xxxx.cms.elasticsearch.domain.HelpCenterContentIndex; import com.xxxx.cms.elasticsearch.manager.ContentIndexManager; import com.xxxx.cms.elasticsearch.repositories.ContentIndexRepository; import com.xxxx.cms.elasticsearch.repositories.HelpCenterRepository; import com.xxxx.cms.tag.common.domain.CmsTagInfo; import com.xxxx.cms.tag.common.service.CmsTagInfoService; import com.xxxx.cms.tag.common.type.TagInfoType; import redis.clients.jedis.JedisCluster; @Repository public class ContentIndexManagerImpl implements ContentIndexManager { private Logger logger = LoggerFactory.getLogger(getClass()); @Autowired private ElasticsearchOperations elasticsearchTemplate; @Autowired private ContentIndexRepository contentIndexRepository; @Autowired private HelpCenterRepository helpCenterRepository; @Resource(name="cmsChannelDefineManager") private CmsChannelDefineManager cmsChannelDefineManager; @Resource(name="jedisClusterClient") private JedisCluster jedisClusterClient; @Autowired @Qualifier("cmsChannelDefineService") private CmsChannelDefineService cmsChannelDefineService; @Autowired @Qualifier("cmsTagInfoService") private CmsTagInfoService cmsTagInfoService; @Autowired private CmsContentTagManager cmsContentTagManager; protected static final String REDIS_CACHE_PREFIX = CacheConstant.ES_PREFIX + "ContentIndexManager" + BaseConstant.REDIS_CACHE_SEPERATOR; public static final String ID_FIELD = "id"; public static final String TITLE_FIELD = "title"; public static final String DESCRIPTION_FIELD = "description"; public static final String CONTENT_TXT_FIELD = "contentTxt"; public static final String RELEASED_DATE_FIELD = "releasedDate"; public static final String CHANNEL_ID_FIELD = "channelId"; public static final String STATUS_FIELD = "status"; public static final String FLAG_BIT_FIELD = "flagBit"; public static final String TAGS_FIELD = "tags"; public static final String RELATED_STOCKS_FIELD = "relatedStocks"; public static final String ANALYZER_NAME = "ik"; @Override public void createCmsContentIndex(CmsContent cmsContent) { ContentIndex snsMsgIndex = new ContentIndex(cmsContent); contentIndexRepository.save(snsMsgIndex); } @Override public DataPage<ContentSearchResult> searchContentByKeyword(String keyword, List<String> filterField, DataPage<ContentSearchResult> dataPage) { return searchContentByKeyword(keyword, filterField, dataPage, null, null); } @Override public List<ContentSearchResult> searchByKeyword(String keyword, int pageSize, int pageNo) { List<ContentSearchResult> searchList = searchByKeyword(keyword, pageSize, pageNo, null, null); //投教标签 setupHelpTag(searchList); return searchList; } private void setupHelpTag(List<ContentSearchResult> searchList) { if (!CollectionUtils.isEmpty(searchList)) { // 查询各篇文章关联的投教标签 List<CmsTagInfo> helpTagList = cmsTagInfoService.queryChildrenByParentId(TagInfoType.HELP_TAG.getIndex()); List<Integer> idList = helpTagList.stream().map(CmsTagInfo::getId).collect(Collectors.toList()); List<Long> contentIdList = searchList.stream().map(ContentSearchResult::getId).collect(Collectors.toList()); Map<String, Object> param = new HashMap<>(); param.put("contentIdList", contentIdList); param.put("tagIdList", idList); List<CmsContentTag> contentTagList = cmsContentTagManager.query(param); Map<Long,List<CmsContentTag>> tagListMap = new HashMap<>(); if (!CollectionUtils.isEmpty(contentTagList)) { for (CmsContentTag tag : contentTagList) { List<CmsContentTag> tagList = tagListMap.get(tag.getContentId()); if (tagList == null) { tagList = new ArrayList<CmsContentTag>(); } tagList.add(tag); tagListMap.put(tag.getContentId(), tagList); } } for (ContentSearchResult content : searchList) { if (tagListMap.get(content.getId()) == null) { content.setTagList(new ArrayList<>()); } else { content.setTagList(tagListMap.get(content.getId())); } } } } @Override public DataPage<ContentSearchResult> searchContentByTags(DataPage<ContentSearchResult> dataPage, Long id, Long channelId, String[] tags) { return searchContentByTags(dataPage, id, channelId, tags , null , null); } @Override public DataPage<ContentSearchResult> searchContentByKeyword(String keyword, List<String> filterField, DataPage<ContentSearchResult> dataPage, String [] esIndexs, String [] esTypes) { logger.info("执行搜索:{}", keyword); NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder(); nativeSearchQueryBuilder.withIndices(esIndexs == null || esIndexs.length == 0 ? new String[] { ElasticSearchConstant.CMS_INDEX } : esIndexs) .withTypes(esTypes == null || esTypes.length == 0 ? new String[] { ElasticSearchConstant.CMS_CONTENT_TYPE } : esTypes); LocalDateTime todayBeginTime = LocalDate.now().atTime(0, 0, 0), todayEndTime = LocalDate.now().atTime(23, 59, 59), now = LocalDateTime.now(); final BoolQueryBuilder boolQuery = boolQuery(); if (CollectionUtils.isEmpty(filterField)) { boolQuery.should(termQuery(TITLE_FIELD, keyword)); boolQuery.should(matchPhraseQuery(TITLE_FIELD, keyword).analyzer(ANALYZER_NAME).slop(1)); boolQuery.should(matchQuery(TITLE_FIELD, keyword).analyzer(ANALYZER_NAME)); // 控制内容的相关度 BoolQueryBuilder txtQuery = boolQuery(); txtQuery.should(matchPhraseQuery(CONTENT_TXT_FIELD, keyword).analyzer(ANALYZER_NAME).slop(5)); txtQuery.should(matchQuery(CONTENT_TXT_FIELD, keyword).analyzer(ANALYZER_NAME).minimumShouldMatch("30%")); boolQuery.should(txtQuery); boolQuery.must(multiMatchQuery(keyword, DESCRIPTION_FIELD + "^2", TAGS_FIELD, RELATED_STOCKS_FIELD) .type(Type.CROSS_FIELDS) .analyzer(ANALYZER_NAME)); } else { if (filterField.contains(TITLE_FIELD)) { boolQuery.should(termQuery(TITLE_FIELD, keyword)); boolQuery.should(matchPhraseQuery(TITLE_FIELD, keyword).analyzer(ANALYZER_NAME).slop(3)); // boolQuery.should(matchQuery(TITLE_FIELD, keyword).operator(Operator.AND).analyzer(WORD_SEPERATOR_NAME)); boolQuery.should(matchQuery(TITLE_FIELD, keyword).analyzer(ANALYZER_NAME).boost(1.2f)); } if (filterField.contains(DESCRIPTION_FIELD)) { BoolQueryBuilder descBoolQuery = boolQuery(); descBoolQuery.should(matchPhraseQuery(DESCRIPTION_FIELD, keyword).analyzer(ANALYZER_NAME).slop(3)); descBoolQuery.should(matchQuery(DESCRIPTION_FIELD, keyword).analyzer(ANALYZER_NAME)); boolQuery.should(descBoolQuery); } if (filterField.contains(CONTENT_TXT_FIELD)) { boolQuery.should(matchPhraseQuery(CONTENT_TXT_FIELD, keyword).analyzer(ANALYZER_NAME).slop(5)); boolQuery.should(matchQuery(CONTENT_TXT_FIELD, keyword).analyzer(ANALYZER_NAME).minimumShouldMatch("20%")); } if (filterField.contains(TAGS_FIELD)) { boolQuery.should(matchPhraseQuery(TAGS_FIELD, keyword).analyzer(ANALYZER_NAME)); boolQuery.should(matchQuery(TAGS_FIELD, keyword).analyzer(ANALYZER_NAME)); } if (filterField.contains(RELATED_STOCKS_FIELD)) { boolQuery.should(matchPhraseQuery(RELATED_STOCKS_FIELD, keyword).analyzer(ANALYZER_NAME)); } } this.general4PeriodQuery(boolQuery, todayBeginTime); this.general4ChannelQuery(boolQuery); nativeSearchQueryBuilder.withQuery(boolQuery); String cacheKey = REDIS_CACHE_PREFIX + "searchContentByKeyword" + BaseConstant.REDIS_CACHE_SEPERATOR + "investmentChannelList", cacheStr = jedisClusterClient.get(cacheKey); // 缓存60分钟 int cacheSecond = 60 * 60; ArrayList<Long> searchChanList = new ArrayList<>(); List<Long> investmentChanList = null; if (StringUtils.isNotEmpty(cacheStr)) { investmentChanList = JSONArray.parseArray(cacheStr, Long.class); searchChanList.addAll(investmentChanList); } else { List<CmsChannelDefine> investmentChannelList = cmsChannelDefineManager .selectAllChildInvestmentChannel(ChannelDefineType.INVESTMENT_CHANNEL.getIndex().longValue()); if (CollectionUtils.isNotEmpty(investmentChannelList)) { investmentChanList = investmentChannelList.stream() .filter(CmsChannelDefine::getIsDisplay) .map(CmsChannelDefine::getId) .collect(Collectors.toList()); cacheStr = JSON.toJSONString(investmentChanList); jedisClusterClient.setex(cacheKey, cacheSecond, cacheStr); searchChanList.addAll(investmentChanList); } } searchChanList.addAll( Arrays.asList( ChannelDefineType.COMB_CHANNEL.getIndex().longValue(), ChannelDefineType.CHINESE_STOCK_CHANNEL.getIndex().longValue(), ChannelDefineType.SINAFIN_CHANNEL.getIndex().longValue(), ChannelDefineType.ZHITONGFIN_YW_CHANNEL.getIndex().longValue() ) ); this.general4FilterOper(nativeSearchQueryBuilder, searchChanList, todayBeginTime, todayEndTime); this.general4HighLightOper(nativeSearchQueryBuilder, keyword); this.general4PageOper(nativeSearchQueryBuilder, dataPage.getPageNo() - 1, dataPage.getPageSize()); // nativeSearchQueryBuilder.withSearchType(SearchType.DFS_QUERY_THEN_FETCH);// 默认是query then fetch,使用默认查询方式 SearchQuery searchQuery = nativeSearchQueryBuilder.build(); // Long totalCount = elasticsearchTemplate.count(searchQuery, ContentIndex.class); List<ContentSearchResult> contentIndexList = this.generalQueryExtractOper(searchQuery); // List<ContentSearchResult> contentIndexList = elasticsearchTemplate.queryForList(searchQuery, ContentSearchResult.class); dataPage.setDataList(contentIndexList); // dataPage.setTotalCount(totalCount); dataPage.setTotalCount(100); LocalDateTime excuteEndTime = LocalDateTime.now(); logger.info("搜索执行时间:{}毫秒", Duration.between(now, excuteEndTime).toMillis()); return dataPage; } private BoolQueryBuilder general4PeriodQuery(final BoolQueryBuilder boolQuery, LocalDateTime todayBeginTime) { LocalDateTime now = LocalDateTime.now(); LocalDateTime threeDaysAgo = todayBeginTime.minusDays(3L), oneWeekAgo = todayBeginTime.minusWeeks(1L), threeMonthsAgo = todayBeginTime.minusMonths(3L), halfOfYearAgo = todayBeginTime.minusMonths(6L); // 3天内的资讯相关度更高 boolQuery.should(rangeQuery(RELEASED_DATE_FIELD) .gt(threeDaysAgo.toInstant(ZoneOffset.ofHours(8)).toEpochMilli()) .lte(now.toInstant(ZoneOffset.ofHours(8)).toEpochMilli()) .boost(15f)); // 一周内的资讯相关度更高 boolQuery.should(rangeQuery(RELEASED_DATE_FIELD) .gt(oneWeekAgo.toInstant(ZoneOffset.ofHours(8)).toEpochMilli()) .lte(threeDaysAgo.toInstant(ZoneOffset.ofHours(8)).toEpochMilli()) .boost(10f)); // 3个月内的资讯相关度更高 boolQuery.should(rangeQuery(RELEASED_DATE_FIELD) .gt(threeMonthsAgo.toInstant(ZoneOffset.ofHours(8)).toEpochMilli()) .lte(oneWeekAgo.toInstant(ZoneOffset.ofHours(8)).toEpochMilli())); // 半年以前的相关度降低 boolQuery.should(rangeQuery(RELEASED_DATE_FIELD) .lte(halfOfYearAgo.toInstant(ZoneOffset.ofHours(8)).toEpochMilli()) .boost(0.6f)); return boolQuery; } private BoolQueryBuilder general4ChannelQuery(final BoolQueryBuilder boolQuery) { // 提高个股资讯的相关度 // boolQuery.should(termQuery(CHANNEL_ID_FIELD, ChannelDefineType.CHINESE_STOCK_CHANNEL.getIndex().longValue())); // 提高自产相关度 // boolQuery.should(termQuery(CHANNEL_ID_FIELD, ChannelDefineType.COMB_CHANNEL.getIndex().longValue())); // 由于暂时不知道ES是否支持位操作,就从业务角度上来说给一个具体值就算了 boolQuery.should(termQuery(FLAG_BIT_FIELD, ContentFlagBitOperUtils.HELP_CENTER_VAL).boost(1.6f)); return boolQuery; } private NativeSearchQueryBuilder general4QueryOper(final NativeSearchQueryBuilder natvSechQBuilder, String keyword, LocalDateTime todayBeginTime) { final BoolQueryBuilder boolQuery = boolQuery(); String minimumShouldMatchStrategy = "3<75%"; // boolQuery.should(matchQuery(TITLE_FIELD, keyword).analyzer(ANALYZER_NAME)); // boolQuery.should(matchQuery(TITLE_FIELD, keyword).analyzer(ANALYZER_NAME).operator(Operator.AND)); // boolQuery.should(multiMatchQuery(keyword, DESCRIPTION_FIELD, CONTENT_TXT_FIELD).tieBreaker(0.4f).minimumShouldMatch(minimumShouldMatchStrategy)); // DisMaxQueryBuilder titleAndDescrptionMaxQuery = disMaxQuery().add(matchQuery(TITLE_FIELD, keyword).analyzer(ANALYZER_NAME)) // .add(matchQuery(DESCRIPTION_FIELD, keyword).analyzer(ANALYZER_NAME)) // .tieBreaker(0.4f) // .queryName("disMaxQueryTest"); // boolQuery.should(titleAndDescrptionMaxQuery); // boolQuery.should(termQuery(TITLE_FIELD, keyword).boost(5f)); boolQuery.should(matchQuery(TITLE_FIELD, keyword).analyzer(ANALYZER_NAME)); boolQuery.should(matchPhraseQuery(TITLE_FIELD, keyword).analyzer(ANALYZER_NAME).type(MatchQueryBuilder.Type.PHRASE_PREFIX).boost(5f)); BoolQueryBuilder titleBoolQuery = boolQuery(); titleBoolQuery.should(termQuery(TITLE_FIELD, keyword)); titleBoolQuery.should(matchPhraseQuery(TITLE_FIELD, keyword).analyzer(ANALYZER_NAME).slop(1)); // boolQuery.should(matchPhrasePrefixQuery(TITLE_FIELD, keyword).analyzer(ANALYZER_NAME).slop(10).maxExpansions(20)); titleBoolQuery.should(matchQuery(TITLE_FIELD, keyword).analyzer(ANALYZER_NAME)); boolQuery.should(titleBoolQuery); BoolQueryBuilder descBoolQuery = boolQuery(); descBoolQuery.should(matchPhraseQuery(DESCRIPTION_FIELD, keyword).analyzer(ANALYZER_NAME)); descBoolQuery.should(matchQuery(DESCRIPTION_FIELD, keyword).analyzer(ANALYZER_NAME)); boolQuery.should(descBoolQuery); // multiMatchQuery(DESCRIPTION_FIELD, keyword).type(MultiMatchQueryBuilder.Type.MOST_FIELDS); boolQuery.should(matchPhraseQuery(CONTENT_TXT_FIELD, keyword).analyzer(ANALYZER_NAME)); boolQuery.should(matchQuery(CONTENT_TXT_FIELD, keyword).analyzer(ANALYZER_NAME)); BoolQueryBuilder contTxtBoolQuery = boolQuery(); contTxtBoolQuery.should(matchPhraseQuery(CONTENT_TXT_FIELD, keyword).analyzer(ANALYZER_NAME).slop(2).minimumShouldMatch(minimumShouldMatchStrategy)); // contTxtBoolQuery.should(matchPhraseQuery(CONTENT_TXT_FIELD, keyword).analyzer(ANALYZER_NAME).slop(2)); contTxtBoolQuery.should(matchQuery(CONTENT_TXT_FIELD, keyword).analyzer(ANALYZER_NAME)); boolQuery.should(contTxtBoolQuery); this.general4ChannelQuery(boolQuery); this.general4PeriodQuery(boolQuery, todayBeginTime); natvSechQBuilder.withQuery(boolQuery); return natvSechQBuilder; } private NativeSearchQueryBuilder general4FilterOper(final NativeSearchQueryBuilder natvSechQBuilder, ArrayList<Long> searchChanlList, LocalDateTime todayBeginTime, LocalDateTime todayEndTime) { BoolQueryBuilder filterQuery = boolQuery(); // 只搜索12个月内的资讯信息 LocalDateTime searchStartTime = todayBeginTime.minusMonths(12L); filterQuery.must(rangeQuery(RELEASED_DATE_FIELD) .gte(searchStartTime.toInstant(ZoneOffset.ofHours(8)).toEpochMilli()) .lte(todayEndTime.toInstant(ZoneOffset.ofHours(8)).toEpochMilli())); if (CollectionUtils.isNotEmpty(searchChanlList)) { filterQuery.must(termsQuery(CHANNEL_ID_FIELD, searchChanlList.toArray())); } filterQuery.must(termQuery(STATUS_FIELD, ContentStatus.PUBLISH.getIndex().intValue())); natvSechQBuilder.withFilter(filterQuery); return natvSechQBuilder; } private NativeSearchQueryBuilder general4HighLightOper(final NativeSearchQueryBuilder natvSechQBuilder, String keyword) { String preTagStr = "<font color=#ff8200>", postTagStr = "</font>"; HighlightBuilder.Field title = new HighlightBuilder.Field(TITLE_FIELD); title.preTags(preTagStr); title.postTags(postTagStr); HighlightBuilder.Field des = new HighlightBuilder.Field(DESCRIPTION_FIELD); des.preTags(preTagStr); des.postTags(postTagStr); natvSechQBuilder.withHighlightFields(title, des); return natvSechQBuilder; } private NativeSearchQueryBuilder general4PageOper(final NativeSearchQueryBuilder natvSechQBuilder, int pageNo, int pageSize) { // spring data的接口是从第0页开始,不要问我为什么 natvSechQBuilder.withPageable(new PageRequest(pageNo, pageSize)); natvSechQBuilder.withMinScore(0.5f);// 相关度不低于50% return natvSechQBuilder; } private List<ContentSearchResult> generalQueryExtractOper(final SearchQuery searchQuery) { return elasticsearchTemplate.query(searchQuery, (SearchResponse response) -> { List<ContentSearchResult> results = new ArrayList<ContentSearchResult>(); for (SearchHit hit : response.getHits()) { ContentSearchResult result = JSON.parseObject(hit.getSourceAsString(), ContentSearchResult.class); Map<String, HighlightField> hlFields = hit.getHighlightFields(); HighlightField titleHLField = hlFields.get(TITLE_FIELD); if (titleHLField != null) { // 取得定义的高亮标签 Text[] titleTexts = titleHLField.getFragments(); // 为title串值增加自定义的高亮标签 String titleStr = ""; for (Text text : titleTexts) { titleStr += text; } // 将追加了高亮标签的串值重新填充到对应的对象 result.setTitle(titleStr); } // 从设定的高亮域中取得指定域 HighlightField descHLField = hlFields.get(DESCRIPTION_FIELD); if (descHLField != null) { // 取得定义的高亮标签 Text[] descTexts = descHLField.fragments(); // 为title串值增加自定义的高亮标签 String desc = ""; for (Text text : descTexts) { desc += text; } // 将追加了高亮标签的串值重新填充到对应的对象 result.setDescription(desc); } logger.info("contentId:{}", result.getId()); results.add(result); } return results; }); } @Override public List<ContentSearchResult> searchByKeyword(String keyword, int pageSize, int pageNo, String[] esIndexs, String[] esTypes) { logger.info("searchByKeywords => 搜索关键词:【{}】 => 开始", keyword); LocalDateTime todayBeginTime = LocalDate.now().atStartOfDay(), todayEndTime = todayBeginTime.plusDays(1L).minusSeconds(1L), now = LocalDateTime.now(); NativeSearchQueryBuilder natvSechQBuilder = new NativeSearchQueryBuilder(); esIndexs = esIndexs == null ? new String[] { ElasticSearchConstant.CMS_INDEX } : esIndexs; esTypes = esTypes == null ? new String[] { ElasticSearchConstant.CMS_CONTENT_TYPE } : esTypes; natvSechQBuilder.withIndices(esIndexs).withTypes(esTypes); // this.general4QueryParam(natvSechQBuilder, keyword, todayBeginTime);// 实用但不直观的写法 natvSechQBuilder = this.general4QueryOper(natvSechQBuilder, keyword, todayBeginTime); String cacheKey = REDIS_CACHE_PREFIX + "searchContentByKeyword" + BaseConstant.REDIS_CACHE_SEPERATOR + "investmentChannelList", cacheStr = jedisClusterClient.get(cacheKey); // 缓存60分钟 int cacheSecond = 60 * 60; ArrayList<Long> searchChanlList = new ArrayList<>(); esTypes = new String[] { ElasticSearchConstant.CMS_CONTENT_TYPE, ElasticSearchConstant.CMS_HELP_CENTER_TYPE };// 过滤时增加帮助中心 for (int i = 0; i < esTypes.length; i++) { String types = esTypes[i]; if (types.equals(ElasticSearchConstant.CMS_CONTENT_TYPE)) { List<Long> investCollegeChanlIdList = null; if (StringUtils.isNotEmpty(cacheStr)) { investCollegeChanlIdList = JSONArray.parseArray(cacheStr, Long.class); searchChanlList.addAll(investCollegeChanlIdList); } else { List<CmsChannelDefine> investCollegeChnlList = cmsChannelDefineManager .selectAllChildInvestmentChannel(ChannelDefineType.INVESTMENT_CHANNEL.getIndex().longValue()); if (CollectionUtils.isNotEmpty(investCollegeChnlList)) { investCollegeChanlIdList = investCollegeChnlList.stream() .filter(CmsChannelDefine::getIsDisplay) .map(CmsChannelDefine::getId) .collect(Collectors.toList()); cacheStr = JSON.toJSONString(investCollegeChanlIdList); jedisClusterClient.setex(cacheKey, cacheSecond, cacheStr); searchChanlList.addAll(investCollegeChanlIdList); } } searchChanlList.addAll( Arrays.asList(ChannelDefineType.COMB_CHANNEL.getIndex().longValue(), ChannelDefineType.CHINESE_STOCK_CHANNEL.getIndex().longValue(), ChannelDefineType.SINAFIN_CHANNEL.getIndex().longValue(), ChannelDefineType.ZHITONGFIN_YW_CHANNEL.getIndex().longValue())); } else if (types.equals(ElasticSearchConstant.CMS_HELP_CENTER_TYPE)) { String cmsCacheKey = cacheKey + "cmshelpcenter"; cacheStr = jedisClusterClient.get(cmsCacheKey); List<Long> cmsHelpCenterLastChild = null; if (StringUtils.isNotEmpty(cacheStr)) { cmsHelpCenterLastChild = JSONArray.parseArray(cacheStr, Long.class); searchChanlList.addAll(cmsHelpCenterLastChild); } else { ModelResult<List<CmsChannelDefine>> listModelResult = cmsChannelDefineService .queryAllChildByParentId(ChannelDefineType.NEW_HELP_CENTER.getIndex().longValue()); List<CmsChannelDefine> cmsChannelDefines = listModelResult.getModel(); if (CollectionUtils.isNotEmpty(cmsChannelDefines)) { cmsHelpCenterLastChild = cmsChannelDefines.stream() .filter(CmsChannelDefine::getIsDisplay) .map(CmsChannelDefine::getId) .collect(Collectors.toList()); cacheStr = JSON.toJSONString(cmsHelpCenterLastChild); jedisClusterClient.setex(cacheKey, cacheSecond, cacheStr); searchChanlList.addAll(cmsHelpCenterLastChild); } } } } // this.general4FilterParam(natvSechQBuilder, searchChanlList, todayBeginTime, todayEndTime);// 实用但不直观的写法 natvSechQBuilder = this.general4FilterOper(natvSechQBuilder, searchChanlList, todayBeginTime, todayEndTime); // this.generalHighLightOper(natvSechQBuilder, keyword, pageNo, pageSize);// 实用但不直观的写法 natvSechQBuilder = this.general4HighLightOper(natvSechQBuilder, keyword); // this.general4PageOper(natvSechQBuilder, pageNo, pageSize);// 实用但不直观的写法 natvSechQBuilder = this.general4PageOper(natvSechQBuilder, pageNo, pageSize); // nativeSearchQueryBuilder.withSearchType(SearchType.DFS_QUERY_THEN_FETCH);// 默认是query then fetch,使用默认查询方式 SearchQuery searchQuery = natvSechQBuilder.build(); Sort sort = new Sort(Direction.DESC, RELEASED_DATE_FIELD); searchQuery.addSort(sort); List<ContentSearchResult> searchResults = this.generalQueryExtractOper(searchQuery); LocalDateTime excuteEndTime = LocalDateTime.now(); logger.info("搜索执行时间:{}毫秒", Duration.between(now, excuteEndTime).toMillis()); return searchResults; } @Override public DataPage<ContentSearchResult> searchContentByTags(DataPage<ContentSearchResult> dataPage, Long id, Long channelId, String[] tags, String[] esIndexs, String[] esTypes) { NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder(); nativeSearchQueryBuilder.withIndices(esIndexs == null || esIndexs.length == 0 ? new String[] { ElasticSearchConstant.CMS_INDEX } : esIndexs) .withTypes(esTypes == null || esTypes.length == 0 ? new String[] { ElasticSearchConstant.CMS_CONTENT_TYPE } : esTypes); BoolQueryBuilder boolQuery = boolQuery(); for (String tag : tags) { boolQuery.should(matchPhraseQuery(TAGS_FIELD, tag)); } //MatchQueryBuilder matchBuilder=new MatchQueryBuilder("channelId", channelId); MatchQueryBuilder matchBuilderId = new MatchQueryBuilder(ID_FIELD, id); //boolQuery.must(matchBuilder); boolQuery.mustNot(matchBuilderId); /* TermsQueryBuilder termsQuery = new TermsQueryBuilder("channelId",channelId+""); boolQuery.must(termsQuery);*/ // TODO nativeSearchQueryBuilder.withFilter(QueryBuilders.termQuery(CHANNEL_ID_FIELD, channelId)); // nativeSearchQueryBuilder // .withFilter(FilterBuilders.andFilter(FilterBuilders.termFilter("channelId", channelId))); this.general4PageOper(nativeSearchQueryBuilder, dataPage.getPageNo() - 1, dataPage.getPageSize()); nativeSearchQueryBuilder.withQuery(boolQuery); SearchQuery searchQuery = nativeSearchQueryBuilder.build(); Sort sort = new Sort(Direction.DESC, RELEASED_DATE_FIELD); searchQuery.addSort(sort); Long totalCount = elasticsearchTemplate.count(searchQuery, ContentIndex.class); List<ContentSearchResult> contentIndexList = elasticsearchTemplate.queryForList(searchQuery, ContentSearchResult.class); dataPage.setDataList(contentIndexList); dataPage.setTotalCount(totalCount); return dataPage; } @Override public void createHelpCenterContentIndex(CmsContent cmsContent) { HelpCenterContentIndex helpCenterContentIndex = new HelpCenterContentIndex(cmsContent); helpCenterRepository.save(helpCenterContentIndex); } }
上一篇: 简单的压测模拟
推荐阅读
-
ThinkPHP实现ajax仿官网搜索功能实例
-
python实现的用于搜索文件并进行内容替换的类实例
-
php数组查找函数in_array()、array_search()、array_key_exists()使用实例
-
Android中搜索图标和文字居中的EditText实例
-
利用PHP+JS实现搜索自动提示(实例)
-
php+ajax做仿百度搜索下拉自动提示框(有实例)
-
微信小程序 搜索框组件代码实例
-
android实现搜索功能并将搜索结果保存到SQLite中(实例代码)
-
PHP实现搜索地理位置及计算两点地理位置间距离的实例
-
荐 Java刷题笔记15:不同的二叉搜索树( Unique Binary Search Trees)