記事ディレクトリ
ES入門
Elasticsearch 7.x は、Lucene をベースとした分散型検索エンジンで、大量のデータを迅速かつ正確に検索、分析、保存できる分散型全文検索エンジンを提供します。Elasticsearch 7.x の主な機能は次のとおりです。
-
分散アーキテクチャ: Elasticsearch 7.x は複数のノードで実行できる分散システムであり、各ノードは互いに独立しており、データは自動的に断片化されて複数のノードにコピーされるため、システムのパフォーマンスが向上し、可用性とスケーラビリティが向上します。
-
リアルタイム検索: Elasticsearch 7.x は、大量のデータのインデックス作成と検索を迅速に行うことができ、リアルタイム検索をサポートしています。つまり、データが変更されたときに、最新の結果をすぐに検索できます。
-
複数のデータ型のサポート: Elasticsearch 7.x は、テキスト、数値、日付、地理的位置などを含む複数のデータ型のインデックス作成と検索をサポートしており、さまざまな種類のデータの検索ニーズを満たすことができます。
-
単語のセグメンテーションと分析: Elasticsearch 7.x は、テキストのセグメンテーションと分析をサポートしています。これにより、テキストを自動的に単語に分解し、インデックスを付けて検索できるため、検索の精度と効率が向上します。
-
RESTful API: Elasticsearch 7.x は、便利で使いやすい HTTP リクエストを通じて Elasticsearch と対話できる RESTful API に基づく操作モードを提供します。
-
多言語サポート: Elasticsearch 7.x は、Java、Python、Ruby、PHP などを含む複数のプログラミング言語のクライアントをサポートしており、これらのクライアントを通じてインデックス作成と検索操作を簡単に実行できます。
-
リアルタイムの監視と診断: Elasticsearch 7.x は、クラスターのステータス、インデックスのパフォーマンス、ノードのステータスなどを簡単に監視できるリアルタイムの監視と診断ツールを提供し、システムの保守性と信頼性を向上させます。
つまり、Elasticsearch 7.x は、さまざまな規模のデータ検索と分析のニーズを満たすことができる、強力で高性能、そして使いやすい分散型検索エンジンです。
基本情報の問い合わせ
すべてのインデックスを表示
# 查看所有索引
GET _cat/indices
green open indexName1 785t4eK4SiarjIj6d_qDtA 1 0 0 0 283b 283b
green open indexName2 7WB8hk3cRMKuTUJhKWni9g 1 0 0 0 283b 283b
green open indexName3 PDJWT_VoS9iWSfEzUe5LEQ 1 0 0 0 283b 283b
green open indexName4 0qc3VwyvS9SIQ97GbILvJw 1 0 0 0 283b 283b
public Set<String> getAllIndex() {
GetAliasesRequest request = new GetAliasesRequest();
GetAliasesResponse response = null;
try {
response = restHighLevelClient.indices().getAlias(request, RequestOptions.DEFAULT);
} catch (IOException e) {
throw new RuntimeException(e);
}
Map<String, Set<AliasMetadata>> aliases = response.getAliases();
Set<String> strings = aliases.keySet();
return strings;
}
インデックスマッピングの表示
# 查看mapping
GET indexName/_mapping
{
"indexName" : {
"mappings" : {
"properties" : {
"field1" : {
"type" : "integer"
},
"field2" : {
"type" : "keyword"
},
"field3" : {
"type" : "integer"
},
"field4" : {
"type" : "long"
},
"field5" : {
"type" : "keyword"
},
"field6" : {
"type" : "integer"
}
}
}
}
public Map<String, String> getMapping(String indexName){
GetMappingsRequest request = new GetMappingsRequest().indices(indexName);
GetMappingsResponse response = null;
try {
response = restHighLevelClient.indices().getMapping(request, RequestOptions.DEFAULT);
} catch (IOException e) {
throw new RuntimeException(e);
}
Map<String, Object> mappings = response.mappings().get(indexName).getSourceAsMap();
Map<String, Map<String, Object>> properties = (Map<String, Map<String, Object>>) mappings.get("properties");
Map<String, String> result = new HashMap<>();
properties.keySet().forEach(key -> {
String value = properties.get(key).get("type").toString();
System.out.println(key);
result.put(key, value);
} );
return result;
}
インデックス内のすべての値を検索します
GET indexName/_search
{
"query":{
"match_all": {
}
}
}
{
"took" : 3,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 10000,
"relation" : "gte"
},
"max_score" : 1.0,
"hits" : [
{
"_index" : "indexName",
"_type" : "_doc",
"_id" : "ngGsfYcB7ZKupvf2r47w",
"_score" : 1.0,
"_source" : {
"field1" : "value1",
"field2" : "value2"
}
},
{
"_index" : "indexName",
"_type" : "_doc",
"_id" : "ngGsfYcB7ZKupvf2r47w",
"_score" : 1.0,
"_source" : {
"field1" : "value1",
"field2" : "value2"
}
}
]
}
}
public List<Map<String, Object>> getAll(String indexName) {
SearchRequest searchRequest = new SearchRequest(indexName);
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder()
.query(QueryBuilders.matchAllQuery())
.size(10000);
searchRequest.source(searchSourceBuilder);
SearchResponse search = null;
try {
search = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
} catch (IOException e) {
throw new RuntimeException(e);
}
SearchHit[] hits = search.getHits().getHits();
List<Map<String, Object>> result = new ArrayList<>();
Arrays.stream(hits).iterator().forEachRemaining(oneDoc -> {
Map<String, Object> sourceAsMap = (Map<String, Object>) oneDoc.getSourceAsMap();
result.add(sourceAsMap);
});
return result;
}
フィルター
ES7.x の bool クエリは複合クエリであり、複数のクエリを組み合わせて複雑な論理演算を実行できます。ブール クエリで一般的に使用されるサブクエリは次のとおりです。
- クエリが必要: 成功した一致とみなされるには、すべてのサブクエリが一致する必要があります。
- must_not クエリ: 成功した一致とみなされるには、すべてのサブクエリが一致しない必要があります。
- Should クエリ: 少なくとも 1 つのサブクエリが正常に一致した場合、一致は成功します。複数の should クエリを指定でき、minimum_Should_match パラメータを使用して、少なくとも一致する必要があるサブクエリの数を制御できます。
- フィルター クエリ:Must クエリに似ていますが、スコアは計算されず、ドキュメントをフィルターするためにのみ使用されます。これらのサブクエリを組み合わせて複雑な論理演算を実行することができ、たとえば、must クエリと should クエリを組み合わせることで、「A と B に一致するか、C に一致する必要がある」というクエリ条件を実現できます。
各サブクエリにはさまざまなフィルター条件があります。
- 等しい: QueryBuilders.termQuery(フィールド名, 値)
- 値の範囲: QueryBuilders.rangeQuery(fieldName).lt(leftValue).gt(rightValue)
- 他にもlte、gte、equalsなどがあります。
次のクエリ ステートメントは、indexName という名前のクエリ インデックスの fileTypeEnum フィールドの値が TEMP である必要があり、タイムスタンプ フィールドの値が 1680769009720 ~ 1680769909720 の範囲内である必要があり、count フィールドの値が 19 であってはいけないことを示しています。
GET /indexName/_search
{
"query": {
"bool": {
"must": [
{
"term": {
"fileTypeEnum": {
"value": "TEMP"
}
}
},
{
"range": {
"timestamp": {
"gte": 1680769009720,
"lte": 1680769909720
}
}
}
],
"must_not": [
{
"term": {
"count": {
"value": "19"
}
}
}
]
}
},
"size": 10000
}
public List<Map<String, Object>> search(String indexName, SearchSourceBuilder searchSourceBuilder) {
SearchRequest searchRequest = new SearchRequest(indexName);
searchRequest.source(searchSourceBuilder);
SearchResponse search = null;
try {
search = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
} catch (IOException e) {
throw new RuntimeException(e);
}
SearchHit[] hits = search.getHits().getHits();
List<Map<String, Object>> result = new ArrayList<>();
Arrays.stream(hits).iterator().forEachRemaining(oneDoc -> {
Map<String, Object> sourceAsMap = (Map<String, Object>) oneDoc.getSourceAsMap();
result.add(sourceAsMap);
});
return result;
}
関数を定義した後は
search
、インデックス名と SearchSourceBuilder オブジェクトを渡すだけで、さまざまなフィルター条件を SearchSourceBuilder オブジェクトに追加できます。
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder()
.query(QueryBuilders.boolQuery().must(QueryBuilders.termQuery("name", "张三")))
.query(QueryBuilders.boolQuery().mustNot(QueryBuilders.rangeQuery("timestape")
.lte(1001)
.gte(1101)));
List<Map<String, Object>> result = search(indexName, searchSourceBuilder);
ファジークエリ
ファジー クエリ: QueryBuilders.wildcardQuery(fieldName, queryString)
*
任意の文字の 0 個以上と一致することを意味します。?
は任意の文字に一致することを意味します。
GET /indexName/_search
{
"query": {
"wildcard": {
"location": "*123*"
}
}
}
{
"took" : 4,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 270,
"relation" : "eq"
},
"max_score" : 1.0,
"hits" : [
{
"_index" : "indexName",
"_type" : "_doc",
"_id" : "ngGsfYcB7ZKupvf2r47w",
"_score" : 1.0,
"_source" : {
"field1" : "value1",
"field2" : "value2"
}
},
{
"_index" : "indexName",
"_type" : "_doc",
"_id" : "ngGsfYcB7ZKupvf2r47w",
"_score" : 1.0,
"_source" : {
"field1" : "value1",
"field2" : "value2"
}
}
]
}
}
List<String> contextLoads(String indexName) throws IOException {
// 模糊搜索
// *表示匹配任意多个字符(包括零个字符)
// ?表示匹配任意单个字符
WildcardQueryBuilder queryWildcard = QueryBuilders.wildcardQuery("location", "*123*");
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder()
.query(queryWildcard)
.from(0) // 设置分页
.size(500) // 默认只显示10个
.fetchSource(new String[]{
"location"}, null) // 只返回location字段
;
SearchRequest searchRequest = new SearchRequest(indexName);
searchRequest.source(searchSourceBuilder);
SearchResponse search = null;
try {
search = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
} catch (IOException e) {
throw new RuntimeException(e);
}
SearchHit[] hits = search.getHits().getHits();
List<String> result = new ArrayList<>();
Arrays.stream(hits).iterator().forEachRemaining(oneDoc -> {
Map<String, Object> sourceAsMap = (Map<String, Object>) oneDoc.getSourceAsMap();
result.add(sourceAsMap.get("location").toString());
});
return result
}
重複排除
IndexName の場所フィールドの重複を除去します。
POST /indexName/_search
{
"size": 0,
"aggs": {
"distinct": {
"terms": {
"field": "location"
}
}
}
}
{
"took" : 3,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 10000,
"relation" : "gte"
},
"max_score" : null,
"hits" : [ ]
},
"aggregations" : {
"distinct" : {
"doc_count_error_upper_bound" : 0,
"sum_other_doc_count" : 688,
"buckets" : [
{
"key" : "30-200-1680592680000",
"doc_count" : 172
},
{
"key" : "30-200-1680592801000",
"doc_count" : 172
},
{
"key" : "30-200-1680593042000",
"doc_count" : 172
},
{
"key" : "30-200-1680593161000",
"doc_count" : 172
}
]
}
}
}
集約による重複排除
public List<String> getDistance() {
SearchRequest searchRequest = new SearchRequest(indexName);
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder()
.aggregation(AggregationBuilders.terms("distinct_location").field("location").size(10));
searchRequest.source(searchSourceBuilder);
SearchResponse searchResponse = null;
try {
searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
} catch (IOException e) {
throw new RuntimeException(e);
}
Terms distinctValues = searchResponse.getAggregations().get("distinct_location");
List<String> collect = distinctValues.getBuckets().stream().map(Terms.Bucket::getKeyAsString).collect(Collectors.toList());
return collect;
}
クエリによる重複排除
List<String> getDistance2() throws IOException {
SearchRequest searchRequest = new SearchRequest(indexName);
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder()
.collapse(new CollapseBuilder("location")) // 根据字段去重
.from(0) // 设置分页
.size(10) // 默认只显示10个
.fetchSource(new String[]{
"location"}, null) // 只返回以上字段
;
searchRequest.source(searchSourceBuilder);
SearchResponse search = null;
try {
search = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
} catch (IOException e) {
throw new RuntimeException(e);
}
SearchHit[] hits = search.getHits().getHits();
List<String> result = new ArrayList<>();
Arrays.stream(hits).iterator().forEachRemaining(oneDoc -> {
Map<String, Object> sourceAsMap = (Map<String, Object>) oneDoc.getSourceAsMap();
result.add(sourceAsMap.get("location").toString());
});
return result;
}
フィルタリング後の重複排除
GET /indexName/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"fileTypeEnum": {
"query": "TEMP"
}
}
},
{
"wildcard": {
"location": "*13*"
}
}
]
}
},
"aggs": {
"distinct": {
"terms": {
"field": "location"
}
}
}
}
String name = "location"; // 名称实际上是 location 字段
// 根据数据类型选择索引名称
SearchRequest searchRequest = new SearchRequest().indices(indexName);
/**
* 封装查询条件
*/
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
// fieldName1
if (StringUtils.isNotEmpty(DTO.getSubsystem())) {
boolQueryBuilder.must(QueryBuilders.termQuery(fieldName1, rawDataAssetsDTO.getSubsystem()));
}
// fieldName1
if (StringUtils.isNotEmpty(DTO.getSubject())) {
boolQueryBuilder.must(QueryBuilders.termQuery(fieldName1, DTO.getSubject()));
}
// 模糊查询 location
if (StringUtils.isNotEmpty(DTO.getLocation())) {
boolQueryBuilder.must(QueryBuilders.wildcardQuery(name, "*" + DTO.getLocation() + "*"));
}
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder()
.query(boolQueryBuilder)
.aggregation(AggregationBuilders.terms("result").field(name).size(100))
;
searchRequest.source(searchSourceBuilder);
SearchResponse searchResponse = null;
try {
searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
} catch (IOException e) {
logger.error("查询ES数据异常:" + e.getMessage());
}
Terms distinctValues = searchResponse.getAggregations().get("result");
List<String> result = distinctValues.getBuckets().stream().map(Terms.Bucket::getKeyAsString).collect(Collectors.toList());
return result;