JavaRestClient(es的java实现)(P123~P141)

客户端初始化

1.引入依赖

<dependency>
    <groupId>org.elasticsearch.client</groupId>
    <artifactId>elasticsearch-rest-high-level-client</artifactId>
</dependency>

2.覆盖默认es版本

在父工程里面指定,因为父工程可以全部匹配,这里用老版本呢是因为新版本api变化太大,而且企业中多用老版本,所以使用老版本。

  <properties>
      <maven.compiler.source>11</maven.compiler.source>
      <maven.compiler.target>11</maven.compiler.target>
      <elasticsearch.version>7.12.1</elasticsearch.version>
  </properties>

3.初始化RestHightClient

RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(
        HttpHost.create("http://192.168.150.101:9200")
));

商品mapping映射

#商品索引库
PUT /hmall
{
  "mappings": {
    "properties": {
      "id":{
        "type": "keyword"
      },
      "name":{
        "type": "text",
        "analyzer": "ik_smart"
      },
      "price":{
        "type": "integer"
      },
      "image":{
        "type": "keyword",
        "index": false
      },
      "category":{
        "type": "keyword"
      },
      "brand":{
        "type": "keyword"
      },
      "sold":{
        "type": "integer"
      },
      "commentCount":{
        "type": "integer",
        "index":false
      },
      "isAD":{
        "type": "boolean"
      },
      "updateTime":{
        "type": "date"
      }
    }
  }
}

索引库操作

public class ElasticTest {

    private RestHighLevelClient client;

    @Test
    void CreatIndex() throws IOException {
        //准备Request对象
        CreateIndexRequest request = new CreateIndexRequest("items");
        //准备请求参数
        request.source(Mapping, XContentType.JSON);
        //发送请求
        client.indices().create(request, RequestOptions.DEFAULT);
    }

    @Test
    void GetIndex() throws IOException {
        //创建对象
        GetIndexRequest request = new GetIndexRequest("items");
        boolean exists = client.indices().exists(request,RequestOptions.DEFAULT);
        System.out.println("exists = "+exists);
    }

    @Test
    void DeleteIndex() throws IOException {
        //创建对象
        DeleteIndexRequest request = new DeleteIndexRequest("items");
        client.indices().delete(request,RequestOptions.DEFAULT);
    }

    @BeforeEach
    void setUp(){
        client = new RestHighLevelClient(RestClient.builder(
                HttpHost.create("http://192.168.202.129:9200")
        ));
    }

    @AfterEach
    void tearDown() throws IOException {
        if(client != null){
            client.close();
        }
    }

    private static final String Mapping = "{\n" +
            "  \"mappings\": {\n" +
            "    \"properties\": {\n" +
            "      \"id\":{\n" +
            "        \"type\": \"keyword\"\n" +
            "      },\n" +
            "      \"name\":{\n" +
            "        \"type\": \"text\",\n" +
            "        \"analyzer\": \"ik_smart\"\n" +
            "      },\n" +
            "      \"price\":{\n" +
            "        \"type\": \"integer\"\n" +
            "      },\n" +
            "      \"image\":{\n" +
            "        \"type\": \"keyword\",\n" +
            "        \"index\": false\n" +
            "      },\n" +
            "      \"category\":{\n" +
            "        \"type\": \"keyword\"\n" +
            "      },\n" +
            "      \"brand\":{\n" +
            "        \"type\": \"keyword\"\n" +
            "      },\n" +
            "      \"sold\":{\n" +
            "        \"type\": \"integer\"\n" +
            "      },\n" +
            "      \"commentCount\":{\n" +
            "        \"type\": \"integer\",\n" +
            "        \"index\":false\n" +
            "      },\n" +
            "      \"isAD\":{\n" +
            "        \"type\": \"boolean\"\n" +
            "      },\n" +
            "      \"updateTime\":{\n" +
            "        \"type\": \"date\"\n" +
            "      }\n" +
            "    }\n" +
            "  }\n" +
            "}";
}

以上便是增删查的所有实现代码。

文档操作

新增文档

@Test
void testAddDocument() throws IOException {
    // 1.根据id查询商品数据
    Item item = itemService.getById(100002644680L);
    // 2.转换为文档类型
    ItemDoc itemDoc = BeanUtil.copyProperties(item, ItemDoc.class);
    // 3.将ItemDTO转json
    String doc = JSONUtil.toJsonStr(itemDoc);

    // 1.准备Request对象
    IndexRequest request = new IndexRequest("items").id(itemDoc.getId());
    // 2.准备Json文档
    request.source(doc, XContentType.JSON);
    // 3.发送请求
    client.index(request, RequestOptions.DEFAULT);
}

记得在类上加

@SpringBootTest(properties = "spring.profiles.active=local")

但是现在存在一个bug就是不管在任何服务单体项目下加上这个就会爆java.lang.IllegalStateException: Failed to load ApplicationContext

删除文档

查询文档

糊涂包里面的toBean是把json转化为你想要的类型

修改文档

第一种全量修改就是直接新增文档,相当于覆盖之前的文档

第二种,局部修改就是下面这种request.doc()调用这个方法。

批处理

page.getRecords就是得到了这一页数据,变为了List<Item>类型的数据。

DSL查询

叶子查询

全文检索

match查询

GET /items/_search
{
  "query": {
    "match": {
      "name": "脱脂牛奶"
    }
  }
}

FIELD是你要查询的字段,TEXT是用户输入的信息。

multi_match查询

GET /items/_search
{
  "query": {
    "multi_match": {
      "query": "脱脂牛奶"
      , "fields": ["name"]
    }
  }
}

TEXT是用户输入的信息,FIELD1,FIELD2是你选择要查询的字段。

精确查询

term

FIELD就是一个字段。

VALUE就是用户输入的内容。

GET /items/_search
{
  "query": {
    "term": {
      "brand": {
        "value": "德雅"
      }
    }
  }
}

range

范围查询

gte是最小值

lte是最大值

复合查询

第一类

案例:搜索智能手机,但品牌必须是华为,价格在900到1599

GET /items/_search
{
  "query": {
    "bool":{
      "must": [
        {
          "match": {
            "name": "智能手机"
          }
        }
      ],
      "filter": [
        {
          "term": {
            "brand": "华为"
          }
        },
        {
          "range": {
            "price": {
              "gte": 900,
              "lte": 1599
            }
          }
        }
      ]
    }
  }
}

第二类

排序和分页

排序

案例:搜索商品,按照销量降序排序,销量一样的则按照价格升序。

GET /items/_search
{
  "query": {
    "match_all": {}
  },
  "sort": [
    {
      "sold": "desc"
      },
      {
        "price": "asc"
      }
  ]
}

分页

案例:搜索商品,查询出销量排名前十的商品,销量一样的时候,按照价格升序

GET /items/_search
{
  "query": {
    "match_all": {}
  },
  "sort": [
    {
      "sold": "desc"
      },
      {
        "price": "asc"
      }
  ]
  , "from": 0,
  "size": 10
}

总体感觉就是es就是另一种搜索功能强大的mysql。

只不过查询返回的数据不好处理。

深度分页问题

es的数据一般会采用分片存储,就是把一个索引中的数据分成n份存储在不同的节点上。查询数据时需要汇总各个分片的数据。

假如查询第100页,每页查10条。

假如我查990——1000,这里es的实现思路是,我先对数据排序,再找出990——1000,先找出前990个

因为数据是混乱保存在节点上的,不能保证每个节点上数据量一样。我们需要在每个分片的前1000找出来合在一起,然后再排序筛选,但是数据量当页码越深,压力就越大。

一般来说是对业务进行了限制,不让查那么多数据。

高亮显示

GET /items/_search
{
  "query": {
    "match": {
      "name": "脱脂牛奶"
    }
  },
  "highlight": {
    "fields": {
      "name": {
        "pre_tags": "<em>",
        "post_tags": "</em>"
      }
    }
  }
}

JavaRestClient查询

快速入门

我们得到的response就是一个大的json结构,所以我们需要解析

我们是为了拿到hit的部分

转化为ItemDoc
ItemDoc doc = JSONUtil.toBean(json,ItemDoc.class);

构建查询条件

排序和分页

高亮显示

数据聚合

DSL实现聚合

GET /hmall/_search
{
  "size": 0,
  "aggs": {
    "cate_agg": {
      "terms": {
        "field": "category",
        "size": 10
      }
    },
    "brand_agg": {
      "terms": {
        "field": "brand",
        "size": 10
      }
    }
  }
}

分组聚合,查询出来的结果就是这样,brand_agg与cate_agg里面装的是数据

我们再打开更里面的数据发现里面是桶,桶里面是数据。

案例:手机价格大于三千的品牌数量。

GET /hmall/_search
{
  "query": {
    "bool": {
      "filter": [{"term": {"category": "手机"}},
      {"range": {"price": {"gte": 300000}}}
      ]
    }
  }, 
  "size": 0,
    "brand_agg": {
      "terms": {
        "field": "brand",
        "size": 10
      }
    }
  }

下面这种类型就是聚合嵌套聚合,原本平级的aggs现在需要嵌套使用。

Java客户端实现聚合

最重要的就是解析结果

这里我们用Aggregation是所有聚合的父亲,并没有实现桶,所以我们用Terms接收。

切记不同的聚合类型要用不同的去接收。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值