builder真的是为了创建复杂的对象而产生的,实际使用场景更侧重复杂对象的构建。
记录一下ES检索复杂对象场景的使用:
首先是抽象层的builder
//构建查询where 条件
interface BuildWhere {
QueryBuilder build();
public static void setDelWhere(final BoolQueryBuilder boolQueryBuilder){
boolQueryBuilder.must(QueryBuilders.termQuery("isDel",0));
boolQueryBuilder.must(QueryBuilders.termQuery("isImageExist",true));
}
}
再看builder实现
class SearchQueryBuilder{
private SearchQueryVo searchQueryVo;
private SearchRequest searchRequest;
public SearchQueryBuilder(final SearchQueryVo searchQueryVo,final ElasticSearchIndexEnum indexEnum) {
this.searchQueryVo = searchQueryVo;
//指定查询的index
searchRequest = new SearchRequest(indexEnum.getValue());
}
public String build(){
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
//查询条件 where
BuildWhere strategy = strategy(searchQueryVo.getSearchTypeEnum());
searchSourceBuilder.query(strategy.build());
//分页limit
searchSourceBuilder.from((searchQueryVo.getCurPage()-1)*searchQueryVo.getPageSize());
searchSourceBuilder.size(searchQueryVo.getPageSize());
/**
* 排序
* 如果是简单查询条件为空时,则按照inputTime desc
* 其他则按照得分 desc
* change:所有查询结果加入排序,时间排序
*/
String order = searchQueryVo.getOrder();
if (StringUtils.isNotBlank(order)) {
if (order.equals(SortOrder.DESC.toString())) {
searchSourceBuilder.sort(new FieldSortBuilder("inputTime").order(SortOrder.DESC));
}else if (order.equals(SortOrder.ASC.toString())){
searchSourceBuilder.sort(new FieldSortBuilder("inputTime").order(SortOrder.ASC));
}
}
searchSourceBuilder.sort(new ScoreSortBuilder().order(SortOrder.DESC));
//预处理prepare
searchRequest.source(searchSourceBuilder);
String searchString = searchService.getSearchString(searchRequest);
log.debug("searchString :{}", searchString);
return searchString;
}
/**
* 自动选择查询类型
* @param searchTypeEnum
* @return
*/
private BuildWhere strategy(SearchTypeEnum searchTypeEnum){
BuildWhere buildWhere = null;
switch (searchTypeEnum){
case simple:
buildWhere = new SimpleBuild();
break;
case height:
buildWhere=new HeightBuild();
break;
case insearch:
buildWhere=new TwiceSearchBuild();
break;
default:
log.error("not found search type of {}",searchTypeEnum);
}
return buildWhere;
}
/**
* 默认创建第一次查询的条件
* @return
*/
private BoolQueryBuilder createBoolQueryBuilder(){
return createBoolQueryBuilder(searchQueryVo.getOnceSearchVo());
}
/**
* 构建一个boolQuery
* @return
*/
private BoolQueryBuilder createBoolQueryBuilder(SearchQueryVo.SearchVo searchVo){
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
if (searchVo == null) {
return boolQueryBuilder;
}
//title(可能出现在多个字段中,这里为了防止可能出现其他字段,用multiMatch)
String title = searchVo.getTitle();
if (StringUtils.isNotBlank(title)) {
boolQueryBuilder.must(QueryBuilders.multiMatchQuery(title,"headline").analyzer("ik_smart"));
}
//图片元素标签
List elementLabel = searchVo.getElementLabel();
if (CollectionUtils.isNotEmpty(elementLabel)) {
//图片元素标签在量字段中查询
BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
boolQuery.should((QueryBuilders.termsQuery("imageScenes.name",elementLabel)));
boolQuery.should((QueryBuilders.termsQuery("imageItems.name",elementLabel)));
boolQueryBuilder.filter(boolQuery);
}
//图片来源
List imageSource = searchVo.getImageSource();
if (CollectionUtils.isNotEmpty(imageSource)) {
boolQueryBuilder.filter(QueryBuilders.termsQuery("imageSource",imageSource));
}
//作者
List newsGrapherName = searchVo.getNewsGrapherName();
if (CollectionUtils.isNotEmpty(newsGrapherName)) {
boolQueryBuilder.filter(QueryBuilders.termsQuery("newsGrapherName",newsGrapherName));
}
//关键词
String keywords = searchVo.getKeywords();
if (StringUtils.isNotBlank(keywords)) {
boolQueryBuilder.must(QueryBuilders.multiMatchQuery(keywords,"caption","headline","searchKey").analyzer("ik_smart"));
}
//开始时间
String imageTimeStart = searchVo.getImageTimeStart();
if (StringUtils.isNotBlank(imageTimeStart)) {
boolQueryBuilder.filter(QueryBuilders.rangeQuery("imageTime").gte(imageTimeStart));
}
//结束时间
String imageTimeEnd = searchVo.getImageTimeEnd();
if (StringUtils.isNotBlank(imageTimeEnd)) {
boolQueryBuilder.filter(QueryBuilders.rangeQuery("imageTime").lte(imageTimeEnd));
}
return boolQueryBuilder;
}
/**
* 简单检索
*/
private class SimpleBuild implements BuildWhere {
/**
* 如果简单查询没有任何条件限制,则返回列表按照时间DESC
* @return
*/
public QueryBuilder build() {
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
String titleOrKeywordOrTag = searchQueryVo.getTitleOrKeywordOrTag();
if (StringUtils.isNotBlank(titleOrKeywordOrTag)) {
MultiMatchQueryBuilder multiMatchQueryBuilder = QueryBuilders.multiMatchQuery(searchQueryVo.getTitleOrKeywordOrTag(), filedNames).analyzer("ik_smart");
boolQueryBuilder.must(multiMatchQueryBuilder);
}
BuildWhere.setDelWhere(boolQueryBuilder);
return boolQueryBuilder;
}
}
/**
* 高级检索
*/
private class HeightBuild implements BuildWhere {
public QueryBuilder build() {
BoolQueryBuilder boolQueryBuilder = createBoolQueryBuilder();
BuildWhere.setDelWhere(boolQueryBuilder);
return boolQueryBuilder;
}
}
/**
* 结果中检索
*/
private class TwiceSearchBuild implements BuildWhere {
public QueryBuilder build() {
//构建第一次查询(最外层条件)
BoolQueryBuilder outBoolQueryBuilder = createBoolQueryBuilder();
//结果中二次筛选查询(第二层条件)
BoolQueryBuilder in1BoolQueryBuilder = createBoolQueryBuilder(searchQueryVo.getTwiceSearchVo());
//将二层条件噻到最外层条件去(这里只能使用boolQuery,才能实现在filter使用match/multi-match 这种全文匹配)
outBoolQueryBuilder.filter(in1BoolQueryBuilder);
BuildWhere.setDelWhere(outBoolQueryBuilder);
return outBoolQueryBuilder;
}
}
}
构建复杂对象,还得是builder.build()。
实际项目中无形中就用到了这些模式,也不用刻意去硬套模式。
在即将结束的职业生涯余光里,没事记录一下自己的代码风格。
本文来自博客园,作者:Eular,转载请注明原文链接:https://www.cnblogs.com/euler-blog/p/18611179
参与评论
手机查看
返回顶部