ElasticSearch 04 -- 进阶

上一篇:ElasticSearch 03 -- 基础使用_fengxianaa的博客-CSDN博客

1. 批量操作

使用 _bulk 命令,是es提供的一种批量增删改的操作API

bulk对JSON串有着严格的要求:每个JSON串一行

POST _bulk
{"delete":{"_index":"hero","_id":"3"}}
{"create":{"_index":"hero","_id":"4"}}
{"name":"西施","skill":"最有价值之物,给最珍贵之人"}
{"update":{"_index":"person","_id":"2"}}
{"doc":{"skill":"让妲己看看你的心"}}

解释:

  • {"delete":{"_index":"hero","_id":"3"}}:删除id是3的数据
  • {"create":{"_index":"hero","_id":"4"}}:添加数据,内容是:{"name":"西施","skill":"最有价值之物,给最珍贵之人"}
  • {"update":{"_index":"hero","_id":"2"}}:更新数据,内容是:{"doc":{"skill":"让妲己看看你的心"}}

结果:id=3的已经删除掉,成功添加 id=4 的数据,成功修改 id=2 的数据

使用 java API:

private static void bulk() throws IOException {
    RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(
        new HttpHost("192.168.56.109",9200,"http")));
    //1. 组装bulk请求对象
    BulkRequest bulkRequest = new BulkRequest();
    //1.1 删除id=4的文档
    DeleteRequest delReq = new DeleteRequest("hero","4");
    bulkRequest.add(delReq);

    //1.2 创建id=5的文档
    Map<String,Object> map = new HashMap<>();
    map.put("name","甄姬");
    map.put("skill","小女子尚在阵前,大丈夫却要回城?");
    IndexRequest createDoc = new IndexRequest("hero")//hero 是索引名
        .id("5")//指定id
        .source(map);//参数也可以螫map
    bulkRequest.add(createDoc);

    //1.3 更新id=1的文档
    Map<String,Object> map2 = new HashMap<>();
    map2.put("skill","没有心,就不会受伤");
    //更新数据也可以使用UpdateRequest,更新指定字段
    UpdateRequest updateRequest = new UpdateRequest("hero","2");
    updateRequest.doc(map2);
    bulkRequest.add(updateRequest);

    BulkResponse responses = client.bulk(bulkRequest, RequestOptions.DEFAULT);
    //输出每个请求的执行结果
    for(BulkItemResponse item : responses.getItems()){
        System.out.println(item.status());
    }
    client.close();
}

Kibana查询:id=4 的已经删除掉,成功添加 id=5 的数据,成功修改 id=2 的数据

使用场景:批量导入数据库中的数据

private static void importData() throws IOException {
    RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(
        new HttpHost("192.168.56.109",9200,"http")));
    BulkRequest bulkRequest = new BulkRequest();
    for(int i =6;i<100;i++){
        Map<String,Object> map = new HashMap<>();
        map.put("name","嫦娥_" + i);
        map.put("skill","像做梦一样");
        IndexRequest createDoc = new IndexRequest("hero")//hero 是索引名
            .id(i + "")//指定id
            .source(map);//参数也可以螫map
        bulkRequest.add(createDoc);
    }
    BulkResponse responses = client.bulk(bulkRequest, RequestOptions.DEFAULT);
    System.out.println(responses.status());
    client.close();
}

2. 查询--重点

1. 查询所有数据

  1. Kibana上脚本使用
# 标准写法
GET hero/_search
{
  "query": {
    "match_all": {}
  }
}
# 非标准:GET person/_search

但是 ES 默认返回10条数据,当然也可以指定返回的条数

# from:从哪里开始,size:指定返回的条数,可以用这俩参数做分页查询
GET hero/_search
{
  "query": {
    "match_all": {}
  },
  "from": 0,
  "size": 3
}

  1. java API
private static void queryAll() throws IOException {
    RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(
        new HttpHost("192.168.56.109",9200,"http")));

    //1. 创建请求对象
    SearchRequest request = new SearchRequest("hero");// hero:索引名
    //1.1 查询条件构造器
    SearchSourceBuilder builder = new SearchSourceBuilder();
    //1.2 组装查询条件,目前是查询所有
    builder.query(QueryBuilders.matchAllQuery());
    //1.3 设置分页条件
    builder.from(0);
    builder.size(5);
    //1.4 把查询条件放到requst中
    request.source(builder);

    //2. 发送查询请求
    SearchResponse response = client.search(request, RequestOptions.DEFAULT);
    //3. 拿到返回结果
    SearchHits hits = response.getHits();
    //3.1 输出总条数
    System.out.println("一共有:" + hits.getTotalHits().value + " 条数据");
    //3.2 取出数据内容
    SearchHit[] arr = hits.getHits();
    for(SearchHit hit : arr){
        String content = hit.getSourceAsString();//以字符串形式获取数据内容
        System.out.println(content);
    }
    client.close();
}

结果:

2. term查询

使用“term”查询,不会对关键字分词,适合查询类型是“keyword”的字段

GET hero/_search
{
  "query": {
    "term": {
      "name": {
        "value": "亚瑟"
      }
    }
  }
}

结果:

java API

private static void termQuery() throws IOException {
    RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(
        new HttpHost("192.168.56.109",9200,"http")));

    SearchRequest request = new SearchRequest("hero");// hero:索引名
    SearchSourceBuilder builder = new SearchSourceBuilder();
    // term查询,使用 termQuery 方法
    builder.query(QueryBuilders.termQuery("name","亚瑟"));
    builder.from(0);
    builder.size(5);
    request.source(builder);

    SearchResponse response = client.search(request, RequestOptions.DEFAULT);
    SearchHits hits = response.getHits();
    System.out.println("一共有:" + hits.getTotalHits().value + " 条数据");
    SearchHit[] arr = hits.getHits();
    for(SearchHit hit : arr){
        String content = hit.getSourceAsString();//以字符串形式获取数据内容
        System.out.println(content);
    }
    client.close();
}

结果:

3. match 查询

先更新一条数据

POST hero/_doc/2
{
    "name":"妲己",
    "skill":"王者荣耀,没有心,就不会受伤"
}

会对查询的关键字分词,然后用分词后的结果分别查询,最后取并集

# match查询
GET hero/_search
{
  "query": {
    "match": {
      "skill": "王者不可阻挡"
    }
  }
}

结果:

因为“王者不可阻挡”的分词结果是:王者、不可、阻挡

查询时,根据:王者、不可、阻挡,分别查询,最后再获取并集,所以结果是2条

但是有时,需要最终结果中同时包含:王者、不可、阻挡,这 3 个词

# match查询,取交集
GET hero/_search
{
  "query": {
    "match": {
      "skill": {
        "query": "王者不可阻挡",
        "operator": "and"
      }
    }
  }
}

分别查询后,取交集,结果:

Java API

private static void matchQuery() throws IOException {
    RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(
        new HttpHost("192.168.56.109",9200,"http")));

    SearchRequest request = new SearchRequest("hero");// hero:索引名
    SearchSourceBuilder builder = new SearchSourceBuilder();
    // match 查询,使用 matchQuery 方法
    builder.query(QueryBuilders.matchQuery("skill","王者不可阻挡").operator(Operator.AND));
    builder.from(0);
    builder.size(5);
    request.source(builder);

    SearchResponse response = client.search(request, RequestOptions.DEFAULT);
    SearchHits hits = response.getHits();
    System.out.println("一共有:" + hits.getTotalHits().value + " 条数据");
    SearchHit[] arr = hits.getHits();
    for(SearchHit hit : arr){
        String content = hit.getSourceAsString();//以字符串形式获取数据内容
        System.out.println(content);
    }
    client.close();
}

结果:

4. 模糊查询

1. 问题

执行下面命令:

# match查询
GET hero/_search
{
  "query": {
    "match": {
      "skill": {
        "query": "王"
      }
    }
  }
}

发现一个结果都没有

这是因为:

  1. 我们存进去的数据经过分词后,没有“王”这个词
  2. 目前我们用的是等值查询

所以,没有结果

2. wildcard

对查询的关键字分词,还可以使用通配符进行模糊查询

  • ?:代表任意单个字符
    • 王?:匹配 ES 的词条中以“王”开头,2个字的词条
  • *:代表0个或多个字符
    • 王*:匹配 ES 的词条中以“王”开头的词条
# wildcard 模糊查询
GET hero/_search
{
  "query": {
    "wildcard": {
      "skill": {
        "value": "王?"
      }
    }
  }
}

java

private static void wildcard() throws IOException {
    RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(
        new HttpHost("192.168.56.109",9200,"http")));

    SearchRequest request = new SearchRequest("hero");// hero:索引名
    SearchSourceBuilder builder = new SearchSourceBuilder();
    // match 查询,使用 matchQuery 方法
    builder.query(QueryBuilders.wildcardQuery("skill","王?"));
    builder.from(0);
    builder.size(5);
    request.source(builder);

    SearchResponse response = client.search(request, RequestOptions.DEFAULT);
    SearchHits hits = response.getHits();
    System.out.println("一共有:" + hits.getTotalHits().value + " 条数据");
    SearchHit[] arr = hits.getHits();
    for(SearchHit hit : arr){
        String content = hit.getSourceAsString();//以字符串形式获取数据内容
        System.out.println(content);
    }
    client.close();
}

结果:

3. 正则

利用正则表达式去查询,只做了解

一个不错的正则网站:regex101: build, test, and debug regex

# 正则表达式查询
GET hero/_search
{
  "query": {
    "regexp": {
      "skill": ".*荣耀"
    }
  }
}

结果:

4. 前缀查询

前缀查询也是一般用于“keyword”类型的字段

# 前缀查询
GET hero/_search
{
  "query": {
    "prefix": {
      "name": {
        "value": "嫦娥_"
      }
    }
  }
}

5. java API

private static void likeQuery() throws IOException {
    RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(
        new HttpHost("192.168.56.109",9200,"http")));

    SearchRequest request = new SearchRequest("hero");// hero:索引名
    SearchSourceBuilder builder = new SearchSourceBuilder();
    // wildcard 查询,使用 wildcardQuery 方法
    //        builder.query(QueryBuilders.wildcardQuery("hero","王?"));
    // 正则查询,使用 regexpQuery 方法
    //        builder.query(QueryBuilders.regexpQuery("hero",".*荣耀"));
    // 前缀查询,使用 prefixQuery 方法
    builder.query(QueryBuilders.prefixQuery("name","嫦娥_"));
    builder.from(0);
    builder.size(5);
    request.source(builder);

    SearchResponse response = client.search(request, RequestOptions.DEFAULT);
    SearchHits hits = response.getHits();
    System.out.println("一共有:" + hits.getTotalHits().value + " 条数据");
    SearchHit[] arr = hits.getHits();
    for(SearchHit hit : arr){
        String content = hit.getSourceAsString();//以字符串形式获取数据内容
        System.out.println(content);
    }
    client.close();
}

5. 范围查询

范围查询也是很常见的操作,比如:

目前我们的数据不支持范围查询,所以重新导入一些

private static void importData() throws IOException {
    RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(
        new HttpHost("192.168.56.109",9200,"http")));
    BulkRequest bulkRequest = new BulkRequest();
    for(int i =6;i<100;i++){
        Map<String,Object> map = new HashMap<>();
        map.put("name","嫦娥_" + i);
        map.put("skill","像做梦一样");
        map.put("skill_num", i);//增加一个字段
        IndexRequest createDoc = new IndexRequest("hero")//hero 是索引名
            .id(i + "")//指定id
            .source(map);//参数也可以螫map
        bulkRequest.add(createDoc);
    }
    BulkResponse responses = client.bulk(bulkRequest, RequestOptions.DEFAULT);
    System.out.println(responses.status());
    client.close();
}
  1. Kibana脚本
# 范围查询
GET hero/_search
{
  "query": {
    "range": {
      "skill_num": {
        "gte": 6,
        "lte": 7
      }
    }
  }
}
# 查询 skill_num>=6 && skill_num<=7 的数据
# 查询 skill_num>6的数据,应该这样写:"gt": 6,

  1. java API
private static void rangeQuery() throws IOException {
     RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(
         new HttpHost("192.168.56.109",9200,"http")));

     SearchRequest request = new SearchRequest("hero");// hero:索引名
     SearchSourceBuilder builder = new SearchSourceBuilder();
     // 范围查询,使用 rangeQuery 方法
     builder.query(QueryBuilders.rangeQuery("skill_num").gte(6).lte(7));
     builder.from(0);
     builder.size(5);
     request.source(builder);

     SearchResponse response = client.search(request, RequestOptions.DEFAULT);
     SearchHits hits = response.getHits();
     System.out.println("一共有:" + hits.getTotalHits().value + " 条数据");
     SearchHit[] arr = hits.getHits();
     for(SearchHit hit : arr){
         String content = hit.getSourceAsString();//以字符串形式获取数据内容
         System.out.println(content);
     }
     client.close();
 }

  1. 排序

根据范围查询一般都会排个序

# 范围查询
GET hero/_search
{
  "query": {
    "range": {
      "skill_num": {
        "gte": 6,
        "lte": 7
      }
    }
  },
  "sort": [
    {
      "skill_num": {
        "order": "desc"
      }
    }
  ]
}
# desc 降序

java API

private static void rangeQuery() throws IOException {
        RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(
                new HttpHost("192.168.56.109",9200,"http")));

        SearchRequest request = new SearchRequest("hero");// hero:索引名
        SearchSourceBuilder builder = new SearchSourceBuilder();
        // 范围查询,使用 rangeQuery 方法
        builder.query(QueryBuilders.rangeQuery("skill_num").gte(6).lte(7));
        builder.from(0);
        builder.size(5);
        // 排序
        builder.sort("skill_num", SortOrder.DESC);
        request.source(builder);

        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        SearchHits hits = response.getHits();
        System.out.println("一共有:" + hits.getTotalHits().value + " 条数据");
        SearchHit[] arr = hits.getHits();
        for(SearchHit hit : arr){
            String content = hit.getSourceAsString();//以字符串形式获取数据内容
            System.out.println(content);
        }
        client.close();
    }

6. 多字段查询

上面我们都是查询单个字段,其实也可以同时查询多个字段

1. queryString

  • 对查询关键字分词,然后用分词后的结果分别查询,最后取并集
  • 可以指定查询多个字段
  1. 查询多个字段
# 分词后,查询多个字段
GET hero/_search
{
  "query": {
    "query_string": {
      "fields": ["skill","name"],
      "query": "亚瑟的荣耀",
      "analyzer": "ik_max_word"
    }
  }
}

  1. 手动对关键字分词
# 分词后,查询多个字段
GET hero/_search
{
  "query": {
    "query_string": {
      "fields": ["skill","name"],
      "query": "亚瑟 AND 荣耀",
      "analyzer": "ik_max_word"
    }
  }
}
# "亚瑟 AND 荣耀":结果中要同时包含 亚瑟 和 荣耀 这两个词条
# "亚瑟 OR 荣耀":结果中要包含 亚瑟 或 荣耀 

2. sampleQueryString

它跟 queryString 的区别是:不支持 OR、AND 这样的连接符

# simple_query_string
GET hero/_search
{
  "query": {
    "simple_query_string": {
      "fields": ["skill","name"],
      "query": "亚瑟 AND 荣耀",
      "analyzer": "ik_max_word"
    }
  }
}
# "亚瑟 AND 荣耀":会切分成 亚瑟 AND 荣耀 3个词, 然后分别查询,最后取并集

返回两个结果

3. java API

private static void queryString() throws IOException {
    RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(
        new HttpHost("192.168.56.109",9200,"http")));

    SearchRequest request = new SearchRequest("hero");// hero:索引名
    SearchSourceBuilder builder = new SearchSourceBuilder();
    // queryString 查询,使用 queryStringQuery 方法
    //        builder.query(QueryBuilders.queryStringQuery("亚瑟的荣耀")
    //                .field("skill").field("name").analyzer("ik_max_word"));

    // simpleQueryString 查询,使用 simpleQueryStringQuery 方法
    builder.query(QueryBuilders.simpleQueryStringQuery("亚瑟 AND 荣耀").field("skill").field("name").analyzer("ik_max_word"));

    request.source(builder);
    SearchResponse response = client.search(request, RequestOptions.DEFAULT);
    SearchHits hits = response.getHits();
    System.out.println("一共有:" + hits.getTotalHits().value + " 条数据");
    SearchHit[] arr = hits.getHits();
    for(SearchHit hit : arr){
        String content = hit.getSourceAsString();//以字符串形式获取数据内容
        System.out.println(content);
    }
    client.close();
}

7. 布尔查询

连接多个查询条件,比如:

关键字:

  • must: 条件必须成立
  • must_not: 条件必须不成立
  • should: 条件可以不成立
  • filter: 条件必须成立,但是性能比 must高,因为不计算分数

默认情况下,ES 会给查询到的结果计算分数,得分高的放到前面

  1. 查询 name="亚瑟",skill 包含 “王者” 的数据
GET hero/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "term": {
            "name": {
              "value": "亚瑟"
            }
          }
        },
        {
          "match": {
            "skill":"王者"
          }
        }
      ]
    }
  }
}

  1. 配合 filter 使用
# 查询 skill 包含 “王者”,name="妲己",的数据
GET hero/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "skill": "王者"
          }
        }
      ],
      "filter": [
        {
          "term": {
            "name": "妲己"
          }
        }
      ]
    }
  }
}

  1. should 条件可以不成立
# 查询 name=亚瑟 或 老亚瑟 的 数据
GET hero/_search
{
  "query": {
    "bool": {
      "should": [
        {
          "term": {
            "name": {
              "value": "亚瑟"
            }
          }
        },
        {
          "term": {
            "name":{
              "value": "老亚瑟"
            }
          }
        }
      ]
    }
  }
}

  1. Java API
private static void boolQuery() throws IOException {
    RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(
        new HttpHost("192.168.56.109",9200,"http")));

    SearchRequest request = new SearchRequest("hero");// person:索引名
    SearchSourceBuilder builder = new SearchSourceBuilder();
    // bool 查询,使用 boolQuery 方法
    builder.query(QueryBuilders.boolQuery()
                  .must(QueryBuilders.matchQuery("skill","王者"))
                  .filter(QueryBuilders.termQuery("name","妲己")));

    request.source(builder);
    SearchResponse response = client.search(request, RequestOptions.DEFAULT);
    SearchHits hits = response.getHits();
    System.out.println("一共有:" + hits.getTotalHits().value + " 条数据");
    SearchHit[] arr = hits.getHits();
    for(SearchHit hit : arr){
        String content = hit.getSourceAsString();//以字符串形式获取数据内容
        System.out.println(content);
    }
    client.close();
}

8. 聚合查询

分为两种:

  • 指标聚合:类似数据库中的:max、min、avg、sum等函数
  • 分组:类似数据库中的 group by

重新生成数据

DELETE hero

# 创建索引,并添加映射
PUT hero
{
  "mappings": {
    "properties": {
      "id":{
        "type": "integer"
      },
      "name":{
        "type":"keyword"
      },
      "skill":{
        "type":"text"
      },
      "skill_num":{
        "type": "integer"
      },
      "type":{
        "type": "keyword"
      }
    }
  }
}

POST _bulk
{"create":{"_index":"hero","_id":"1"}}
{"id":1,"name":"亚瑟","skill":"王者,以圣剑的名义,冲锋","skill_num":3,"type":"战士"}
{"create":{"_index":"hero","_id":"2"}}
{"id":2,"name":"妲己","skill":"王者,没有心,就不会受伤","skill_num":3,"type":"法师"}
{"create":{"_index":"hero","_id":"3"}}
{"id":3,"name":"甄姬","skill":"王者,还人间一片净土","skill_num":3,"type":"法师"}
{"create":{"_index":"hero","_id":"4"}}
{"id":4,"name":"西施","skill":"王者,最有价值之物,给最珍贵之人","skill_num":3,"type":"法师"}

GET hero/_search
  1. 指标聚合
# 查询 skill 中包含 王者 的数据,并拿到结果中最大的skill_num
GET hero/_search
{
  "query": {
    "match": {
      "skill": "王者"
    }
  },
  "aggs": {
    "max_skill_num": {
      "max": {
        "field": "skill_num"
      }
    }
  }
}
# "max_skill_num" 是自己定义的字段名,之后会在结果中展示

  1. 分组
# 查询所有数据,并对结果中的 type 进行分组,取分组后的前10条数据
GET hero/_search
{
  "query": {
    "match_all": {}
  },
  "aggs": {
    "type_group": {
      "terms": {
        "field": "type",
        "size": 10
      }
    }
  }
}

  1. Java API
private static void aggQuery() throws IOException {
    RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(
        new HttpHost("192.168.56.109",9200,"http")));

    SearchRequest request = new SearchRequest("hero");// hero:索引名
    SearchSourceBuilder builder = new SearchSourceBuilder();
    builder.query(QueryBuilders.matchAllQuery());
    /**
         * 组装聚合条件
         *  name_group:自定义的名字,获取数据使用
         *  name:分组的字段名
         */
    AggregationBuilder aggBuilder = AggregationBuilders.terms("type_group").field("type").size(10);
    builder.aggregation(aggBuilder);

    request.source(builder);
    SearchResponse response = client.search(request, RequestOptions.DEFAULT);
    // 获取聚合结果
    Aggregation groupResult = response.getAggregations().asMap().get("type_group");
    // 获取分组结果,需要把 groupResult 转换为 Term
    List<? extends Terms.Bucket> buckets = ((Terms) groupResult).getBuckets();
    for(Terms.Bucket bucket : buckets){
        System.out.println(bucket.getKey() + "----" + bucket.getDocCount());
    }
    client.close();
}

9. 结果高亮

让查询的结果高亮显示,比如:

其实本质就是设置了一个样式

  1. Kibana演示
# 对查询结果高亮
GET hero/_search
{
  "query": {
    "match": {
      "skill": "王者荣耀"
    }
  },
  "highlight": {
    "fields": {
      "skill": {
        "pre_tags": "<font color='red'>",
        "post_tags": "</font>"
      }
    }
  }
}

 

  1. Java API
private static void highLight() throws IOException {
    RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(
        new HttpHost("192.168.56.109",9200,"http")));

    SearchRequest request = new SearchRequest("hero");// hero:索引名
    SearchSourceBuilder builder = new SearchSourceBuilder();
    builder.query(QueryBuilders.matchQuery("skill","王者荣耀"));

    //设置高亮条件
    HighlightBuilder highlightBuilder = new HighlightBuilder();
    highlightBuilder.field("skill").preTags("<font color='red'>").postTags("</font>");
    builder.highlighter(highlightBuilder);
    request.source(builder);

    SearchResponse response = client.search(request, RequestOptions.DEFAULT);
    SearchHits hits = response.getHits();
    System.out.println("一共有:" + hits.getTotalHits().value + " 条数据");

    SearchHit[] arr = hits.getHits();
    for(SearchHit hit : arr){
        //获取高亮结果
        Map<String, HighlightField> highlightFields = hit.getHighlightFields();
        //拿到高亮的字段
        HighlightField addressField = highlightFields.get("skill");
        //获取高亮的数据,是一个数组,我们文档比较简单,取数组的第一个就行了
        String address = addressField.getFragments()[0].string();
        Map<String, Object> map = hit.getSourceAsMap();
        //用高亮的数据替换查询到的结果
        map.put("skill", address);
        System.out.println(map);
    }
    client.close();
}

3. 索引重建

随着业务的发展,索引的结构可能发生变化。但是 ES 规定,一旦索引创建就只能添加字段,不能修改字段

因为改变字段需要重建:倒排索引,性能太低。

ES提供了另一种方式:重建索引,并把老的索引数据导入到新的索引中

演示:

# 1. 新建一个 student1 索引,只有一个 birth 字段,date类型
PUT student1
{
  "mappings": {
    "properties": {
      "birth":{
        "type": "date"
      }
    }
  }
}
# 2. 存储一条数据
PUT student1/_doc/1
{
  "birth":"2000-01-01"
}

这时候业务变更,birth字段需要存储 “2000年1月1日”,这样的字符串,如果还用老的索引结构会报错

PUT student1/_doc/2
{
  "birth":"2000年1月1日"
}

并且 ES 也不支持修改字段类型

这时候只能重建索引

# 1. 建立一个新的索引:student2, 设置 birth 为 text 类型
PUT student2
{
  "mappings": {
    "properties": {
      "birth":{
        "type": "text"
      }
    }
  }
}
# 2. 导入老的索引数据
POST _reindex
{
  "source": {
    "index": "student1"
  },
  "dest": {
    "index": "student2"
  }
}
# 3. 存放一条数据
PUT student2/_doc/2
{
  "birth":"2000年1月1日"
}

# 4. 查询数据
GET student2/_search

查询 student2 的数据

但是这时,我们代码中用的还是老索引名,再修改代码明显不现实

ES 提供了给索引设置别名,来解决这种问题:

  • 删除老的索引
  • 给新的索引设置别名
# 1. 删除老索引
DELETE student1

# 2. 给新的索引设置别名
POST student2/_alias/student1

# 3. 通过别名也能查询到数据
GET student1/_search


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值