版本定位:7.x

总结的坑:

  1. term及terms词条查询时,如果有text及keyword类型,则需加'.keyword'
  2. queryString全字段搜索时,最好指定字段;并要提前设置好字段mapping:keyword并指定分词器。
  3. reindex做数据迁移时,先创建一个新索引,然后指定源索引与新创建的目标索引,此时会出现502超时。解决方式:
  • 增加分片数slices=9,及wait_for_completion=false异步执行,也可用size指定每批次数量提高效率。
  • 返回任务task:ID。
  • 请求,返回状态信息。GET /_tasks/ID

数据迁移请求:

POST /_reindex?slices=9&refresh&wait_for_completion=false
{
  "source": {
    "index": "source_index",
    "size": 1000
  },
  "dest": {
    "index": "target_index"
  }
}

4. ik分词器版本问题:如果没有elasticseach对应的版本的ik,可以下载相近版本ik,并把ik里的properties文件的elaticsearch.version改成应用版本即可。

5. 时间格式转换,如果把原来的text-keword类型直接更改为date类型,那么原有的时间格式的数据转换失败,需在更换为date类型时,并指定时间格式:"format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"。
6.得分排序时,必需要匹配查询,优先使用自定义得分搜索排序
7.为空时给个设定的默认值,以便布尔查询过滤的时候可以查出:示例:

PUT /es_test
{
  "mappings": {
    "properties": {
      "tags": {
        "type": "keyword",
        "null_value": "null"  // 为空时,默认为"null",显示为null。用布尔过滤的单词条可以查出
      },
      "brand_id": {
        "type": "keyword"    // 没有加空值默认值时,显示依然为null。但是不能查出。
      }
    }
  }
}

8.默认查询前一万条数据,如果分页导致查询一万条之后的数据,需要设置

PUT /es_test/_settings
{
  "index":{
    "max_result_window":10000000
  }
}

9.聚合去重

GET /es_test/_search
{
  "track_total_hits": true, 
  "query": {
    "match_all": {}
  },
  "collapse": {
    "field": "product_id"
  },
  "aggs": {
    "search_total": {
      "cardinality": {
        "field": "product_id"
      }
    }
  }
}


// 对应Java代码            
// 折叠去重“product_id”
CollapseBuilder collapseBuilder = new CollapseBuilder(SearchConstants.QUERY_PRODUCT_INFO_BOOL_QUERY_COLUMN.PRODUCT_ID);
// 聚合去重计算总数,这里聚合存在误差,设置精确度最大
AggregationBuilder cardinalityAggregationBuilder = AggregationBuilders.cardinality(SearchConstants.AGG_CONSTRANTS.CARDINALITY_NAME).field(SearchConstants.QUERY_PRODUCT_INFO_BOOL_QUERY_COLUMN.PRODUCT_ID)
                    .precisionThreshold(40000L);

其中返回值:

  • hits中total的总条数实际上是去重前的总条数,原数据条数,这里我们知道就行,分页中我们并不使用它。hits中数组的大小刚好等于courseAgg聚合的值,数组中的数据就是去重后的数据。
  • aggregations中的courseAgg条数,这个才是去重后的实际条数,也是分页用的总条数。

10.分词匹配时,特殊英文符号解析时会报错,要对字符串转义过滤后再搜索。转义方法:

public static String escape(String s) {
         StringBuilder sb = new StringBuilder();
         for (int i = 0; i < s.length(); i++) {
             char c = s.charAt(i);
             if (c == '\\' || c == '+' || c == '-' || c == '!' || c == '(' || c == ')' || c == ':'
                     || c == '^' || c == '[' || c == ']' || c == '\"' || c == '{' || c == '}' || c == '~'
                     || c == '*' || c == '?' || c == '|' || c == '&' || c == '/') {
                 sb.append('\\');
             }
             sb.append(c);
         }
         return sb.toString();
     }


或者直接用escape方法