大数据开发Elasticsearch高级进阶(第六十篇)

370 阅读7分钟

一、Settings设置

可以设置索引库的一些配置信息,主要针对分片数量和副本数量。分片数量只能在一开始创建索引库的时候指定,后期不能修改,副本数量可以随时修改

curl -XGET 'http://192.168.234.100:9200/user/_settings?pretty'

返回的结果:

{
  "user" : {
    "settings" : {
      "index" : {
        "routing" : {
          "allocation" : {
            "include" : {
              "_tier_preference" : "data_content"
            }
          }
        },
        "number_of_shards" : "1",
        "provided_name" : "user",
        "creation_date" : "1677417886981",
        "number_of_replicas" : "1",
        "uuid" : "oBCobIUjTruqKYYLpNVC7w",
        "version" : {
          "created" : "7170699"
        }
      }
    }
  }
}
1.1、手工指定分片数量
curl -H "Content-Type:application/json" -XPUT 'http://192.168.234.100:9200/test1' -d '{"settings":{"number_of_shards":5,"number_of_replicas":1}}'

返回结果

{
  "test1" : {
    "settings" : {
      "index" : {
        "routing" : {
          "allocation" : {
            "include" : {
              "_tier_preference" : "data_content"
            }
          }
        },
        "number_of_shards" : "5",
        "provided_name" : "test1",
        "creation_date" : "1677681909514",
        "number_of_replicas" : "1",
        "uuid" : "eWXdyJ51RyO7G6B2gzrWew",
        "version" : {
          "created" : "7170699"
        }
      }
    }
  }
}
1.2、通过settings修改副本数量
curl -H "Content-Type:application/json" -XPUT 'http://192.168.234.100:9200/test1/_settings' -d '{"index":{"number_of_replicas":0}}'

重新查询下信息:

{
  "test1" : {
    "settings" : {
      "index" : {
        "routing" : {
          "allocation" : {
            "include" : {
              "_tier_preference" : "data_content"
            }
          }
        },
        "number_of_shards" : "5",
        "provided_name" : "test1",
        "creation_date" : "1677681909514",
        "number_of_replicas" : "0",
        "uuid" : "eWXdyJ51RyO7G6B2gzrWew",
        "version" : {
          "created" : "7170699"
        }
      }
    }
  }
}

二、mapping

表示索引库中数据的字段类型信息,类似于MySQL中的表结构信息,默认我们不需要手工指定mapping,因为ES会根据数据格式识别它的类型。如果说你需要对某一些字段添加一些特殊的属性。例如我们想要自己指定分词器,这个时候就必须要手工指定字段的mapping。也就是mapping对应的是数据类型。

数据格式数据类型
字符串text、keyword
数字long、double
日期date
布尔型true、false
二进制binary

Text类型支持分词,并且也支持模糊、精确查询,但是它不支持聚合和排序操作,Text类型不限制存储的内容长度,它适合大字段存储。

keyword类型不支持分词,它会直接对数据建立索引,也支持模糊、精确来源,支持聚合和排序操作。最大支持存储的内容长度为32766个utf-8类型的字符。可以通过设置ignore_above这个参数来指定某个字段最大支持的字符长度,超过这个长度的数据不再被索引。这个时候就没有办法通过termQuery去精确查询那个数据了。因为数据太长了。在设置了最大限度,超过这个长度就截掉了,后期再通过原始的数据去精确查询,肯定查不到了,如果没有超过这个最大长度,查询是没有问题的。适合存储:手机号、姓名等等,这些不需要分词的数据

普通整数会识别为long,小数会识别为double。当然也可以手工指定integer、short、byte、float这些数据类型

最常用的类型是date,这个类型可以支持到毫秒,如果特殊情况下我们需要精确到纳秒,这时候可以使用date_nanos类型。其中针对这个date类型,我们可以自定义日期格式,可以使用时间戳,或者使用年月日格式,可以通过format参数来指定这个日期格式

binary,它可以存储编码为Base64字符串的二进制,如果想要存储一些图片,可以存储图片地址或者图片本身,存储图片本身就需要用到binary

curl -XGET 'http://192.168.234.100:9200/user/_mapping?pretty'

返回内容:

{
  "user" : {
    "mappings" : {
      "properties" : {
        "age" : {
          "type" : "long"
        },
        "name" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        }
      }
    }
  }
}

手工创建指定类型

curl -H "Content-Type:application/json" -XPUT 'http://192.168.234.100:9200/test2' -d '{"mappings":{"properties":{"name":{"type":"text","analyzer":"ik_max_word"},"age":{"type":"integer"}}}}'

查询mappings,返回:

{
  "test2" : {
    "mappings" : {
      "properties" : {
        "age" : {
          "type" : "integer"
        },
        "name" : {
          "type" : "text",
          "analyzer" : "ik_max_word"
        }
      }
    }
  }
}

三、ES的偏好查询

ES中的索引数据,最终都是存储在分片里面,分片有多个,并且分片还分为主分片和副本分片。

比如有3个节点3个分片:Node1是master(r0、p1)、node2(r0、r1)、node3(p0、r1) ES查询的步骤:

  1. 客户端发送一个查询请求发送到node3上面,node3会创建一个空优先队列,主要是为了存储数据结果
  2. node3负责将查询请求转发到索引的主分片上或者副本分片里面。比如分发到p1和ro这两个分片里面,每个分片在本地执行查询,并且将查询到的结果添加到有序的优先队列里面。node3是随机转发的,也可以由程序员控制
  3. 每个分片会返回各自优先队列中所有文档的id和排序值,返回给node3,node3会合并这些数据,把它们合并到自己的优先队列里面,产生全局排序后的结果列表

注意:当客户端的一个搜索请求被发送到某个节点的时候,这个节点它就变成了一个协调节点,这个节点的任务是广播查询请求到所有的相关分片,并且将它们查询到的结果整合成全局排序后的结果集合,这个结果集合最终会返回给客户端。

那么如何控制查询请求到分片之间的一个分发规则呢?

package com.strivelearn.es;
​
import org.apache.http.HttpHost;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
​
import java.io.IOException;
​
/**
 * @author strivelearn
 * @version EsPreferenceOp.java, 2023年03月02日
 */
public class EsPreferenceOp {
    public static void main(String[] args) throws IOException {
        RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(new HttpHost("192.168.234.100", 9200)));
        SearchRequest searchRequest = new SearchRequest();
        // 指定索引库,支持指定一个或者多个,也支持通配符,例如:user*
        searchRequest.indices("user");
​
        // 指定分片查询方式 默认是随机的
        searchRequest.preference();
​
        client.close();
    }
}
  1. _local:表示查询操作会优先在本地节点(协调节点)的分片中查询,没有的话再到其它节点中查询

    searchRequest.preference("_local");
    
  2. _only_local:表示查询只会在本地节点的分片中查询

  3. _only_nodes:表示只在指定的节点中查询

    这种方式需要指定节点id。获取节点id的方式:

    http://192.168.234.100:9200/_nodes?pretty
    

    image-20230302224216766

    searchRequest.preference("_only_nodes:bZJSMPN4Q4qVnpMXMfn7nw");
    
  4. _prefer_nodes:表示优先在指定的节点上查询

    searchRequest.preference("_prefer_nodes:bZJSMPN4Q4qVnpMXMfn7nw");
    
  5. _shards:表示只查询索引库中指定分片的数据

    searchRequest.preference("_shards:0,1");
    
  6. custom-string:自定义一个参数,不能以下划线(_)开头

四、ES中的routing路由功能

ES在添加数据时候,会根据数据的id或者routing参数做一个hash,得到的hash值再与该索引库的分片数量取模,得到的值即为存入的分片编号。如果说有多条数据使用相同的routing参数,那么最终计算出来的分片编号肯定是一样的,那么这些数据就可以存储到相同的分片里面,后期我们查询的时候,就只需要到指定分片中查询就可以,可以显著提高查询性能。

ES的极速查询就是routing

新增数据的时候指定routing
curl -H "Content-Type:application/json" -XPOST 'http://192.168.234.100:9200/routtest/_doc/1?routing=testrouting' -d '{"name":"zhangsan","age":18}'
private static void addIndexByJson(RestHighLevelClient client) throws IOException {
    IndexRequest request = new IndexRequest("test");
    request.id("10");
    String json = "{ "name": "zhangsan"}";
    request.source(json);
    request.routing("testrouting");
    client.index(request, RequestOptions.DEFAULT);
}
查询的时候指定routing
searchRequest.routing("testrouting");

五、ES SQL

针对ES中的结构化数据,也可以使用SQL实现聚合统计,比较方便,可以减少很多工作量。ES SQL支持常见的SQL语法,包括分组、排序、函数等,但是目前不支持JOIN等其他函数。支持SQL命令行、RestAPI、JDBC、ODBC等方式操作

切换elastic用户,进入es的安装目录,输入:

bin/elasticsearch-sql-cli http://bigdata01:9200

进入的界面如下:

image-20230302231902009

输入sql语句:

select * from user;

Java代码编写

引入pom依赖

<dependency>
    <groupId>org.elasticsearch.plugin</groupId>
    <artifactId>x-pack-sql-jdbc</artifactId>
    <version>7.17.6</version>
</dependency>

java代码

package com.strivelearn.es;
​
import java.sql.*;
import java.util.Properties;
​
/**
 * @author strivelearn
 * @version EsJdbcOp.java, 2023年03月02日
 */
public class EsJdbcOp {
    public static void main(String[] args) throws SQLException {
        String esJdbcStr = "jdbc:es://http://bigdata01:9200/?timezone=UTC+8";
        Properties props = new Properties();
        Connection connection = DriverManager.getConnection(esJdbcStr, props);
        Statement statement = connection.createStatement();
        ResultSet resultSet = statement.executeQuery("select * from user");
        while (resultSet.next()) {
            String name = resultSet.getString(1);
            Integer age = resultSet.getInt(2);
            System.out.println(name + "---" + age);
        }
        statement.close();
        connection.close();
    }
}

image-20230302232811838

目前我这个版本需要购买license,需要使用的话,同上面的代码一样。实际开发中,使用api接口多,很少使用es sql的方式来获取数据,了解下即可