天天看點

ElasticSearch 6.x 小結

ES version:6.8.8,spring-boot-starter-data-elasticsearch:2.1.0.RELEASE,spring-data-elasticsearch:3.1.2.RELEASE,org.elasticsearch.client:6.2.2

1.ES 在建立索引時,text:會進行分詞,keyword:不會進行分詞,這樣在進行查詢時,全量查詢查keyword字段時可以命中使用分詞器查詢就無法查詢到;全量查詢text字段無法命中用分詞器查詢比對到則會命中。

2.match和term的差別:term不會分詞,match會被分詞(.analyzer(“analyzer”))一般模糊查找的時候多用match,而精确查找時可以使用term。

3.term查詢keyword字段需要完全比對才可,term全量比對text分詞的結果才可

4.match分詞後需要與keyword全量比對才可,隻要match的分詞結果和text的分詞結果有比對即可

5.match_phrase是分詞的,text也是分詞的。match_phrase的分詞結果必須在text字段分詞中都包含,而且順序必須相同,而且必須都是連續的。(text:he is a boy,match_phrase:is a 可,is boy 不可,is a girl 不可)

6.query_string是分詞的,查詢text類型的字段不需要連續,順序還可以調換。

7.實作 “title”==“a” or (“createrOnly” == true and “createrId” == “b”) or (“projectOnly” == true and “projectId” in [“c”,“d”,“e”])

String[] projectIds = req.getProjectId().split(",");

NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();
// es計數從0開始
Pageable pageable = PageRequest.of(req.getPageNum() - 1, req.getSize());
builder.withPageable(pageable);

BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
boolQueryBuilder.must(QueryBuilders.matchQuery("title", req.getTitle()));
boolQueryBuilder
.should(QueryBuilders.boolQuery()
        .must(QueryBuilders.termQuery("createrOnly", true))
        .must(QueryBuilders.termQuery("createrId.keyword", req.getCreaterId())))
.should(QueryBuilders.boolQuery()
              .must(QueryBuilders.termQuery("projectOnly", true))
              .must(QueryBuilders.termsQuery("projectId.keyword", projectIds)));
builder.withFilter(boolQueryBuilder);
Page<clazz> page = elasticsearchTemplate.queryForPage(builder.build(), clazz);

JSONObject json = new JSONObject();
json.put("totle", page.getTotalElements());
json.put("pageNum", page.getPageable().getPageNumber() + 1);
json.put("pageSize", page.getPageable().getPageSize());
json.put("items", page.getContent());
           

8.term做精确查詢可以用它來處理數字,布爾值,日期以及文本,當查詢字元串且 fields包含text、keyword類型時需要在字段名後拼上**.keyword**這是 es 之 termQuery 精确查詢失效問的一個大坑(ES在建立索引時預設 fields類型:參考第9條),否則隻能 match 分詞查詢,最保險的方法是使用kibana查詢mapping進行索引檢視後再開發。對于多個 must、should 在 sql 中以 [] 包裹多個條件逗号分隔:should:{bool:must[a,b]}

GET myindex/_search
{
  "query": {
    "bool": {
      "must": [
        {"match": {
          "title": "小豬"
        }}
      ], 
      "should": [
        {
          "bool": {
            "must": [
              {
                "term": {
                  "createrOnly": {
                    "value": true
                  }
                }
              },
              {
                "term": {
                  "createrId.keyword": {
                    "value": "UDP43f1d0787b16447e82d645f9175fd29e"
                  }
                }
              }
            ]
          }
        },
        {
          "bool": {
            "must": [
              {
                "term": {
                  "projectId": {
                    "value": true
                  }
                }
              },
              {
                "terms": {
                  "projectId.keyword": [
                    "P-2eb738ef48344ef497b60fa5ffae6151",
                    "P-2eb738ef48344ef497b60fa5ffae6152"
                  ]
                }
              }
            ]
          }
        }
      ]
    }
  }
}
           

9.使用注解 Bean 建立索引無論建立類型 text、keyword,es 預設都會引入 fields 支援分詞查詢和精确查詢

ElasticSearch 6.x 小結

10.建立索引

// createIndex = false 建議關閉啟動檢測索引,沒有則建立的配置
@Document(indexName = "docindex", type = "doctype", createIndex = false)
boolean exist = elasticsearchTemplate.indexExists(clazz);
if(!exist) {
	elasticsearchTemplate.createIndex(clazz);
	elasticsearchTemplate.putMapping(clazz);
}
// 表示該字段是一個文本,并作最大程度拆分,預設建立索引
@Field(type=FieldType.Text, analyzer="ik_max_word")
// 表示該字段是一個文本,不建立索引
@Field(type=FieldType.Text,index=false)
// 表示該字段是一個文本,日期類型,預設不建立索引
@Field(type=FieldType.Date)
// 表示該字段是一個長整型,預設建立索引
@Field(type=FieldType.Long)
// 表示該字段内容是一個文本并作為一個整體不可分,預設建立索引
@Field(type=FieldType.Keyword)
// 表示該字段内容是一個浮點類型并作為一個整體不可分,預設建立索引
@Field(type=FieldType.Float)                               
 
// date 、float、long 都是不能夠被拆分的

// 在指定分詞索引後,也可以指定查詢索引
boolQueryBuilder.must(QueryBuilders.matchQuery("title", req.getTitle()).analyzer("ik_smart"));
           

11.當索引不在滿足于資料查詢時,又不想包括資料重頭再來時就需要:索引遷移

PUT /new_index
{
// 建立新索引
}
// 遷移
POST _reindex
{
  "source": {
    "index": "old_index"
  },
  "dest": {
    "index": "new_index"
  }
}
           

繼續閱讀