微服务Day7学习

文章目录

数据聚合

聚合分类

自动补全


DSL实现Bucket聚合



DSL实现Metrics聚合

RestAPI实现聚合

测试类

java 复制代码
    @Test
    void testAggregation() throws IOException {
        //1.准备Request
        SearchRequest request = new SearchRequest("hotel");
        //2.准备DSL
        //2.1 设置size
        request.source().size(0);
        //2.2 聚合
        request.source().aggregation(AggregationBuilders
                .terms("brandAgg")
                .field("brand")
                .size(20));
        //3.发出请求
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        //4.解析结果
        System.out.println(response);
    }
java 复制代码
    @Test
    void testAggregation() throws IOException {
        //1.准备Request
        SearchRequest request = new SearchRequest("hotel");
        //2.准备DSL
        //2.1 设置size
        request.source().size(0);
        //2.2 聚合
        request.source().aggregation(AggregationBuilders
                .terms("brandAgg")
                .field("brand")
                .size(20));
        //3.发出请求
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        //4.解析结果
        Aggregations aggregations = response.getAggregations();
        //4.1 根据聚合名称获取聚合结果
        Terms brandTerms = aggregations.get("brandAgg");
        //4.2 获取buckets
        List<? extends Terms.Bucket> buckets = brandTerms.getBuckets();
        //4.3 遍历
        for (Terms.Bucket bucket : buckets) {
            //4.4获取key
            String key = bucket.getKeyAsString();
            System.out.println(key);
        }
    }

多条件聚合

Service实现类中

java 复制代码
    @Override
    public Map<String, List<String>> filters() {
        //1.准备Request
        SearchRequest request = new SearchRequest("hotel");
        //2.准备DSL
        //2.1 设置size
        request.source().size(0);
        //2.2 聚合
        buildAggregation(request);
        //3.发出请求
        SearchResponse response = null;
        try {
            response = client.search(request, RequestOptions.DEFAULT);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        //4.解析结果
        Map<String, List<String>> result = new HashMap<>();
        Aggregations aggregations = response.getAggregations();
        //4.1 根据名称获取品牌结果 并放入map
        List<String> brandList = getAggByName(aggregations,"brandAgg");
        result.put("品牌", brandList);
        List<String> cityList = getAggByName(aggregations,"cityAgg");
        result.put("城市", cityList);
        List<String> starList = getAggByName(aggregations,"starAgg");
        result.put("星级", starList);
        return result;
    }

    private List<String> getAggByName(Aggregations aggregations,String aggName) {
        //4.1 根据聚合名称获取聚合结果
        Terms brandTerms = aggregations.get(aggName);
        //4.2 获取buckets
        List<? extends Terms.Bucket> buckets = brandTerms.getBuckets();
        //4.3 遍历
        List<String> brandList = new ArrayList<>();
        for (Terms.Bucket bucket : buckets) {
            //4.4获取key
            String key = bucket.getKeyAsString();
            brandList.add(key);
        }
        return brandList;
    }

    private void buildAggregation(SearchRequest request) {
        request.source().aggregation(AggregationBuilders
                .terms("brandAgg")
                .field("brand")
                .size(100));
        request.source().aggregation(AggregationBuilders
                .terms("cityAgg")
                .field("city")
                .size(100));
        request.source().aggregation(AggregationBuilders
                .terms("starAgg")
                .field("starName")
                .size(100));
    }

对接前端接口

拼音分词器


自定义分词器



自动补全查询


实现酒店搜索框自动补全

DSK代码

js 复制代码
DELETE /hotel
# 酒店数据索引库
PUT /hotel
{
  "settings": {
    "analysis": {
      "analyzer": {
        "text_anlyzer": {
          "tokenizer": "ik_max_word",
          "filter": "py"
        },
        "completion_analyzer": {
          "tokenizer": "keyword",
          "filter": "py"
        }
      },
      "filter": {
        "py": {
          "type": "pinyin",
          "keep_full_pinyin": false,
          "keep_joined_full_pinyin": true,
          "keep_original": true,
          "limit_first_letter_length": 16,
          "remove_duplicated_term": true,
          "none_chinese_pinyin_tokenize": false
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "id":{
        "type": "keyword"
      },
      "name":{
        "type": "text",
        "analyzer": "text_anlyzer",
        "search_analyzer": "ik_smart", 
        "copy_to": "all"
      },
      "address":{
        "type": "keyword",
        "index": false
      },
      "price":{
        "type": "integer"
      },
      "score":{
        "type": "integer"
      },
      "brand":{
        "type": "keyword",
        "copy_to": "all"
      },
      "city":{
        "type": "keyword"
      },
      "starName":{
        "type": "keyword"
      },
      "business":{
        "type": "keyword",
        "copy_to": "all"
      },
      "location":{
        "type": "geo_point"
      },
      "pic":{
        "type": "keyword",
        "index": false
      },
      "all":{
        "type": "text",
        "analyzer": "text_anlyzer",
        "search_analyzer": "ik_smart"
      },
      "suggestion":{
          "type": "completion",
          "analyzer": "completion_analyzer"
      }
    }
  }
}

GET /hotel/_search
{
  "query": {
    "match_all": {}
  }
}

GET /hotel/_search
{
  "suggest": {
    "suggestions": {
      "text": "",
      "completion": {
        "field": "suggestion",
        "skip_duplicates": true,
        "size": 10
      }
    }
  }
}

修改实体类

java 复制代码
@Data
@NoArgsConstructor
public class HotelDoc {
    private Long id;
    private String name;
    private String address;
    private Integer price;
    private Integer score;
    private String brand;
    private String city;
    private String starName;
    private String business;
    private String location;
    private String pic;
    private Object distance;
    private Boolean isAD;
    private List<String> suggestion;

    public HotelDoc(Hotel hotel) {
        this.id = hotel.getId();
        this.name = hotel.getName();
        this.address = hotel.getAddress();
        this.price = hotel.getPrice();
        this.score = hotel.getScore();
        this.brand = hotel.getBrand();
        this.city = hotel.getCity();
        this.starName = hotel.getStarName();
        this.business = hotel.getBusiness();
        this.location = hotel.getLatitude() + ", " + hotel.getLongitude();
        this.pic = hotel.getPic();
        if (this.business.contains("/")){
            //business有多个点,需要切割
            String[] arr = this.business.split("/");
            //添加元素
            this.suggestion = new ArrayList<>();
            this.suggestion.add(this.brand);
            Collections.addAll(this.suggestion, arr);
        }else {
            this.suggestion = Arrays.asList(this.brand,this.business);
        }
    }
}

建立测试类

java 复制代码
    @Test
    void testSuggest() throws IOException {
        //1.准备Request
        SearchRequest request = new SearchRequest("hotel");
        //2.准备DSL
        request.source().suggest(new SuggestBuilder().
                addSuggestion("suggestions", SuggestBuilders
                        .completionSuggestion("suggestion")
                        .prefix("h")
                        .skipDuplicates(true)
                        .size(10)
                ));
        //3.发起请求
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        ///4.解析结果
        System.out.println(response);
    }

测试类

java 复制代码
    @Test
    void testSuggest() throws IOException {
        //1.准备Request
        SearchRequest request = new SearchRequest("hotel");
        //2.准备DSL
        request.source().suggest(new SuggestBuilder().
                addSuggestion("suggestions", SuggestBuilders
                        .completionSuggestion("suggestion")
                        .prefix("h")
                        .skipDuplicates(true)
                        .size(10)
                ));
        //3.发起请求
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        ///4.解析结果
        Suggest suggest = response.getSuggest();
        //4.1根据补全查询名称获取补全结果
        CompletionSuggestion suggestions = suggest.getSuggestion("suggestions");
        //4.2 获取options
        List<CompletionSuggestion.Entry.Option> options = suggestions.getOptions();
        //4.3 遍历
        for (CompletionSuggestion.Entry.Option option : options) {
            String text = option.getText().toString();
            System.out.println(text);
        }
    }
java 复制代码
    @Override
    public List<String> getSuggestions(String prefix) {
        //1.准备Request
        SearchRequest request = new SearchRequest("hotel");
        //2.准备DSL
        request.source().suggest(new SuggestBuilder().
                addSuggestion("suggestions", SuggestBuilders
                        .completionSuggestion("suggestion")
                        .prefix(prefix)
                        .skipDuplicates(true)
                        .size(10)
                ));
        //3.发起请求
        SearchResponse response = null;
        try {
            response = client.search(request, RequestOptions.DEFAULT);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        ///4.解析结果
        Suggest suggest = response.getSuggest();
        //4.1根据补全查询名称获取补全结果
        CompletionSuggestion suggestions = suggest.getSuggestion("suggestions");
        //4.2 获取options
        List<CompletionSuggestion.Entry.Option> options = suggestions.getOptions();
        //4.3 遍历
        List<String> list = new ArrayList<>(options.size());
        for (CompletionSuggestion.Entry.Option option : options) {
            String text = option.getText().toString();
            list.add(text);
        }
        return list;
    }

数据同步

数据同步思路分析




利用mq实现mysql与elasticsearch数据同步



声明excahnge、queue、RoutingKey

java 复制代码
public class MqConstants {
    //交换机
    public final  static String HOTEL_EXCHANGE = "hotel.topic";
    //新增修改的队列
    public final  static String HOTEL_INSERT_QUEUE = "hotel.insert.queue";
    //删除队列
    public final  static String HOTEL_DELETE_QUEUE = "hotel.delete.queue";
    //新增获修改RoutingKey
    public final  static String HOTEL_INSERT_KEY = "hotel.insert";
    //删除的RoutingKey
    public final  static String HOTEL_DELETE_KEY = "hotel.delete";
}
java 复制代码
@Configuration
public class MqConfig {
    @Bean
    public TopicExchange topicExchange(){
        return new TopicExchange(MqConstants.HOTEL_EXCHANGE,true,false);
    }
    @Bean
    public Queue insertQueue(){
        return new Queue(MqConstants.HOTEL_INSERT_QUEUE,true);
    }
    @Bean
    public Queue deleteQueue(){
        return new Queue(MqConstants.HOTEL_DELETE_QUEUE,true);
    }
    @Bean
    public Binding insertQueueBinding(){
        return BindingBuilder.bind(insertQueue()).to(topicExchange()).with(MqConstants.HOTEL_INSERT_KEY);
    }
    @Bean
    public Binding deleteQueueBinding(){
        return BindingBuilder.bind(deleteQueue()).to(topicExchange()).with(MqConstants.HOTEL_DELETE_KEY);
    }
}

yaml配置

yml 复制代码
  rabbitmq:
    host: xxx.xxx.x.xxx(主机地址)
    port: 5672
    username: itcast
    password: 123321
    virtual-host: /

在hotel-admin中增、删、改业务中完成消息发送

mq组件

java 复制代码
@Component
public class HotelListener {
    @Autowired
    private IHotelService hotelService;
    /**
     * 监听酒店新增或修改的业务
     * @param id
     */
    @RabbitListener(queues = MqConstants.HOTEL_INSERT_QUEUE)
    public void listenHotelInsertOrUpdate(Long id){
        hotelService.insertById(id);
    }

    /**
     * 监听酒店删除的业务
     * @param id
     */
    @RabbitListener(queues = MqConstants.HOTEL_DELETE_QUEUE)
    public void listenHotelDelete(Long id){
        hotelService.deleteById(id);
    }
}

实现类

java 复制代码
    @Autowired
    private RabbitTemplate rabbitTemplate;
        @PostMapping
    public void saveHotel(@RequestBody Hotel hotel){
        hotelService.save(hotel);
        rabbitTemplate.convertAndSend(MqConstants.HOTEL_EXCHANGE, MqConstants.HOTEL_INSERT_KEY, hotel.getId());
    }

    @PutMapping()
    public void updateById(@RequestBody Hotel hotel){
        if (hotel.getId() == null) {
            throw new InvalidParameterException("id不能为空");
        }
        hotelService.updateById(hotel);
        rabbitTemplate.convertAndSend(MqConstants.HOTEL_EXCHANGE, MqConstants.HOTEL_INSERT_KEY, hotel.getId());
    }

    @DeleteMapping("/{id}")
    public void deleteById(@PathVariable("id") Long id) {
        hotelService.removeById(id);
        rabbitTemplate.convertAndSend(MqConstants.HOTEL_EXCHANGE, MqConstants.HOTEL_DELETE_KEY, id);

    }

在hotel-demo中完成消息监听,并更新elasticsearch中的数据

java 复制代码
    @Override
    public void deleteById(Long id) {
        //1.准备Request
        DeleteRequest request = new DeleteRequest("hotel",id.toString());
        //2.准备发送请求
        try {
            client.delete(request, RequestOptions.DEFAULT);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public void insertById(Long id) {
        //0.根据id查询酒店数据
        Hotel hotel = getById(id);
        //转换文档类型
        HotelDoc hotelDoc = new HotelDoc(hotel);
        //1.准备Request
        IndexRequest request = new IndexRequest("hotel").id(hotel.getId().toString());
        //2.准备JSON文档
        request.source(JSON.toJSONString(hotelDoc), XContentType.JSON);
        //3.准备发送请求
        try {
            client.index(request, RequestOptions.DEFAULT);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

集群

介绍

搭建ES集群

yml 复制代码
version: '2.2'
services:
  es01:
    image: docker.elastic.co/elasticsearch/elasticsearch:7.12.1
    container_name: es01
    environment:
      - node.name=es01
      - cluster.name=es-docker-cluster
      - discovery.seed_hosts=es02,es03
      - cluster.initial_master_nodes=es01,es02,es03
      - bootstrap.memory_lock=true
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
    ulimits:
      memlock:
        soft: -1
        hard: -1
    volumes:
      - data01:/usr/share/elasticsearch/data
    ports:
      - 9200:9200
    networks:
      - elastic
  es02:
    image: docker.elastic.co/elasticsearch/elasticsearch:7.12.1
    container_name: es02
    environment:
      - node.name=es02
      - cluster.name=es-docker-cluster
      - discovery.seed_hosts=es01,es03
      - cluster.initial_master_nodes=es01,es02,es03
      - bootstrap.memory_lock=true
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
    ulimits:
      memlock:
        soft: -1
        hard: -1
    volumes:
      - data02:/usr/share/elasticsearch/data
    networks:
      - elastic
  es03:
    image: docker.elastic.co/elasticsearch/elasticsearch:7.12.1
    container_name: es03
    environment:
      - node.name=es03
      - cluster.name=es-docker-cluster
      - discovery.seed_hosts=es01,es02
      - cluster.initial_master_nodes=es01,es02,es03
      - bootstrap.memory_lock=true
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
    ulimits:
      memlock:
        soft: -1
        hard: -1
    volumes:
      - data03:/usr/share/elasticsearch/data
    networks:
      - elastic

volumes:
  data01:
    driver: local
  data02:
    driver: local
  data03:
    driver: local

networks:
  elastic:
    driver: bridge








相关推荐
九圣残炎20 分钟前
【从零开始的LeetCode-算法】1456. 定长子串中元音的最大数目
java·算法·leetcode
wclass-zhengge22 分钟前
Netty篇(入门编程)
java·linux·服务器
lulu_gh_yu26 分钟前
数据结构之排序补充
c语言·开发语言·数据结构·c++·学习·算法·排序算法
Re.不晚1 小时前
Java入门15——抽象类
java·开发语言·学习·算法·intellij-idea
雷神乐乐1 小时前
Maven学习——创建Maven的Java和Web工程,并运行在Tomcat上
java·maven
码农派大星。1 小时前
Spring Boot 配置文件
java·spring boot·后端
顾北川_野1 小时前
Android 手机设备的OEM-unlock解锁 和 adb push文件
android·java
江深竹静,一苇以航1 小时前
springboot3项目整合Mybatis-plus启动项目报错:Invalid bean definition with name ‘xxxMapper‘
java·spring boot
confiself1 小时前
大模型系列——LLAMA-O1 复刻代码解读
java·开发语言
Wlq04151 小时前
J2EE平台
java·java-ee