项目要求:客户可以筛选不同的index 并且可以进行多条条件的筛选。

刚开始,一开始对于需求不够明确,认为搜索条件中的 第四个条件 “或or且”是针对于当前条件单独的描述。例如,名字等于xxx (且) 且表示当前条件必须成立。但是这样的理解是不正确的。
正确的查询:且表示上下俩条数据都必须存在,或表示当前条件可以存在可以不存在。
而后,被公司的大哥指点了一番,通过大集合小集合先对条件进行了处理,然后进行查询,完成的高级查询。

解决思路:首先以“或”作为条件的分割, 如果在条件列表中,出现了或,则证明或后面的条件是单独的条件,例如:A and B or C 那么证明我们想要的查询其实为(A and B) or C
对条件列表进行遍历, 当列表的长度为1或者2的时候单独处理,当条件条数大于3的时候,首先判断当前条件中 是 或or且 如果是且,那么将且封装进入一个小的list 然后进行下一次遍历,如果当前条件中需求为或,那么证明之前的条件+当前条件为组合,所以将当前条件装入小list 然后将小list装入大list中,每次遇到或。都进行将数据加入小list ,然后将小list加入大list 然后给小list重新创建对象(一开始是调用了list.clear,但是这个方法会将内存中所有小list的引用都清除,但是我们是要保存大list中小list的数据的),这样循环下去,将不同的条件都封装在大list中,大list中包含多个小list 小list中包含多个条件,各个小list之间的关系是or 小list中各个条件之间的关系为and
对应到es的dsl语句为:

POST mhdz,tlsmz,wbswxx,hotel/_search
{
  "profile": "true",
  "query": {
    "bool": {
      "should": [
        {
          "bool": {
            "must": [
              {
                "multi_match": {
                  "query": "李四",
                  "fields": [
                    "xm",
                    "xm.keyword"
                  ],
                  "boost": 0.5,
                  "minimum_should_match": "75%"
                }
              },
              {
                "match": {
                  "zjhm": {
                    "query": "3604251999061622",
                    "boost": 3,
                    "fuzziness": "AUTO"
                  }
                }
              }
            ]
          }
        },
        {
          "bool": {
            "must": [
              {
                "multi_match": {
                  "query": "张三",
                  "fields": [
                    "xm",
                    "xm.keyword"
                  ],
                  "boost": 0.5,
                  "minimum_should_match": "75%"
                }
              },
              {
                "match": {
                  "zjhm": {
                    "query": "3604251999061122",
                    "boost": 3,
                    "fuzziness": "AUTO"
                  }
                }
              }
            ]
          }
        }
      ]
    }
  }
}
private SearchRequest getSynQueryResultByCondition(HashMap<String, Object> bindParams) {
    SearchRequest searchRequest;
    // 获取查询的索引列表
    String[] indexNames = (String[]) bindParams.get("indexKeys");

    // 获取查询的条件列表
    List<HashMap<String, String>> options = (List<HashMap<String, String>>) bindParams.get("conditions");
    // 1.构建查询请求
    if (indexNames != null && indexNames.length > 0) {
        searchRequest = new SearchRequest(indexNames);
    } else {
        // 所有的名称
        EsIndex esIndex = new EsIndex();
        esIndex.setDelFlag(false);
        String[] indexArray = esIndexService.select(esIndex).stream().map(EsIndex::getIndexKey).toArray(String[]::new);
        searchRequest = new SearchRequest(indexArray);
    }
    // 4.构建最外面的boolQuery
    BoolQueryBuilder query = QueryBuilders.boolQuery();
    if (options != null && options.size() > 0) {
        // 大list
        ArrayList<List<HashMap<String, String>>> orList = Lists.newArrayList();
        // 小list
        ArrayList<HashMap<String, String>> andList = Lists.newArrayList();
        for (int i = 0; i < options.size(); i++) {
            // 如果只有一条数据,直接装入orList
            if (options.size() == 1) {
                andList.add(options.get(i));
                orList.add(andList);
                break;
            }
            String searchRelation = options.get(i).get("searchRelation");
            // 如果有俩条数据,判断他们的关系
            if (options.size() == 2) {
                if (Integer.toString(SearchRelationEnum.Q.getKey()).equals(searchRelation)) {
                    orList.add(options);
                } else {
                    andList.add(options.get(0));
                    orList.add(andList);
                    andList = new ArrayList<>();
                    andList.add(options.get(1));
                    orList.add(andList);
                }
                break;
            }
            // 三条以上 判断倒数第二条是且还是或,最后一条不考虑且或
            if (i == options.size() - 2) {
                if (Integer.toString(SearchRelationEnum.Q.getKey()).equals(searchRelation)) {
                    andList.add(options.get(i));
                    andList.add(options.get(i + 1));
                    orList.add(andList);
                } else {
                    andList.add(options.get(i));
                    orList.add(andList);
                    andList = new ArrayList<>();
                    andList.add(options.get(i + 1));
                    orList.add(andList);
                }
                break;
            }
            // 如果是且 装入小list
            if (Integer.toString(SearchRelationEnum.Q.getKey()).equals(searchRelation)) {
                andList.add(options.get(i));
            } else {
                // 如果是或 先装入小的,然后装入大的,然后清空小的
                andList.add(options.get(i));
                orList.add(andList);
                andList = new ArrayList<>();
            }
        }

        orList.forEach(or -> {
            BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
            for (HashMap<String, String> stringHashMap : or) {
                // 获取搜索前提条件
                String searchPremise = stringHashMap.get("searchPremise");
                // 获取搜索符号
                String searchSymbol = stringHashMap.get("searchSymbol");
                // 获取搜索内容
                String searchContent = stringHashMap.get("searchContent");
                // 索取搜索关系
                String analyzeType = stringHashMap.get("analyzeType");
                //判断analyzeType 是否等于 0 如果等于0 则证明他是keyword 字段,不需要分词,
                if ("0".equals(analyzeType)){
                    // 判断searchSymbol是等于还是包含。如果是等于 设置他的前提条件为searchSymbol
                    analyzeType = "whitespace";
                }else {
                    if (Integer.toString(SearchSymbolEnum.DY.getKey()).equals(searchSymbol)){
                        analyzeType = "whitespace";
                        searchPremise =  searchPremise + ".keyword";
                    }
                }
                // 查询query 姓名 等于 或
                // 判断前提条件是否为姓名
                if ("xm".equals(searchPremise)) {
                    QueryBuilder multiQuery;
                    // 判断搜索符号是等于还是包含
                    // 如果是等于
                    if (Integer.toString(SearchSymbolEnum.DY.getKey()).equals(searchSymbol)) {
                        // 对于xm字段,xm的keyword字段 进行多字段查询,当条件为必须等于的时候,将查询条件不分词完成必须完全匹配
                        multiQuery = QueryBuilders.multiMatchQuery(searchContent, "xm", "xm.keyword").analyzer(analyzeType).boost((float) 0.5);
                        boolQuery.must(multiQuery);
                    } else if (Integer.toString(SearchSymbolEnum.BH.getKey()).equals(searchSymbol)) {
                        // 包含关系中 姓名必须匹配75%以上,才会返回
                        multiQuery = QueryBuilders.multiMatchQuery(searchContent, "xm", "xm.keyword").minimumShouldMatch("75%").boost((float) 0.5);
                        // 如果是且
                        boolQuery.must(multiQuery);
                    }
                } else if ("lxdh".equals(searchPremise)) {
                    // 手机号码查询设置查询时可以出错,可出错的个数由ES决定
                    QueryBuilder matchQuery = QueryBuilders.matchQuery("lxdh", searchContent).fuzziness("AUTO").boost(3);
                    boolQuery.must(matchQuery);
                } else if ("zjhm".equals(searchPremise)) {
                    QueryBuilder matchQuery = QueryBuilders.matchQuery("zjhm", searchContent).fuzziness("AUTO").boost(5);
                    boolQuery.must(matchQuery);
                } else{
                    QueryBuilder multiMatchQuery = QueryBuilders.multiMatchQuery(searchContent,searchPremise).analyzer(analyzeType);
                    boolQuery.must(multiMatchQuery);}
            }
            query.should(boolQuery);
        });
    }
    //6.高亮
    HighlightBuilder highlightBuilder = new HighlightBuilder();
    // 所有查询出来的字段全部高亮
    HighlightBuilder.Field highlightTitle = new HighlightBuilder.Field("*").requireFieldMatch(false);
    highlightTitle.highlighterType("unified");
    highlightBuilder.field(highlightTitle);
    // 3.构建高亮
    SearchSourceBuilder sourceBuilder = new SearchSourceBuilder().query(query).highlighter(highlightBuilder);
    // 2.将查询构建器放入查询请求中
    searchRequest.source(sourceBuilder);

    return searchRequest;
}