草庐IT

ES实战 | 黑马旅游案例

阿伟在自律 2023-11-21 原文

关键词搜索

需求:根据文字搜索,也可以选择标签搜索

思路:用bool查询,先根据关键词查询全部,再根据标签过滤。

public class HotelService extends ServiceImpl<HotelMapper, Hotel> implements IHotelService {
    @Autowired
    private RestHighLevelClient client;
    @Override
    public PageResult search(RequestParams params) throws IOException {
        SearchRequest request = new SearchRequest("hotel");
//        关键字搜索
        QueryBuilder query = buildBasicQuery(params);
        request.source().query(query);
        
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        return extracted(response);
    }

    private static QueryBuilder buildBasicQuery(RequestParams params) {
        String key  = params.getKey();
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
//        query
//        关键字搜索
        if ("".equals(key) || key==null){
            boolQuery.must(QueryBuilders.matchAllQuery());
        }else {
            boolQuery.must(QueryBuilders.matchQuery("all",key));
        }
//        过滤条件
        if (params.getMinPrice()!=null && params.getMaxPrice()!=null){
            boolQuery.filter(QueryBuilders.rangeQuery("price").gte(params.getMinPrice()).lte(params.getMaxPrice()));
        }
        if (!("".equals(params.getCity()) || params.getCity()==null)){
            boolQuery.filter(QueryBuilders.termQuery("city", params.getCity()));
        }
        if (!("".equals(params.getBrand()) || params.getBrand()==null)){
            boolQuery.filter(QueryBuilders.termQuery("brand", params.getBrand()));
        }
        if (!("".equals(params.getStarName()) || params.getStarName()==null)){
            boolQuery.filter(QueryBuilders.termQuery("starName", params.getStarName()));
        }
        return boolQuery;
    }

    private static PageResult extracted(SearchResponse response) {
        SearchHits searchHits = response.getHits();
        long total = searchHits.getTotalHits().value;
        SearchHit[] hits = searchHits.getHits();
        List<HotelDoc> list = Arrays.stream(hits).map(item -> {
            String jsonStr = item.getSourceAsString();
            Object[] sortValues = item.getSortValues();
            HotelDoc hotelDoc = JSONObject.parseObject(jsonStr, HotelDoc.class);
            return hotelDoc;
        }).collect(Collectors.toList());
        return new PageResult(total, list);
    }
}

分页排序

需求:实现分页排序

思路:分页跟排序是单独的功能,可以根据选项排好序再分页

@Service
public class HotelService extends ServiceImpl<HotelMapper, Hotel> implements IHotelService {
    @Autowired
    private RestHighLevelClient client;
    private static Boolean isLocation = false;
    @Override
    public PageResult search(RequestParams params) throws IOException {
        SearchRequest request = new SearchRequest("hotel");
//        关键字搜索
        QueryBuilder query = buildBasicQuery(params);
        request.source().query(query);
//        分页
        int page = params.getPage();
        int size = params.getSize();
        request.source().from((page-1)*size).size(size);
//        排序
        if (!("default".equals(params.getSortBy()))){
            FieldSortBuilder sortBy = SortBuilders.fieldSort(params.getSortBy());
            if ("price".equals(params.getSortBy())){
                sortBy.order(SortOrder.ASC);
            }else {
                sortBy.order(SortOrder.DESC);
            }
            request.source().sort(sortBy);
        }
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        return extracted(response);
    }

    private static QueryBuilder buildBasicQuery(RequestParams params) {
        String key  = params.getKey();
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
//        query
//        关键字搜索
        if ("".equals(key) || key==null){
            boolQuery.must(QueryBuilders.matchAllQuery());
        }else {
            boolQuery.must(QueryBuilders.matchQuery("all",key));
        }
//        过滤条件
        if (params.getMinPrice()!=null && params.getMaxPrice()!=null){
            boolQuery.filter(QueryBuilders.rangeQuery("price").gte(params.getMinPrice()).lte(params.getMaxPrice()));
        }
        if (!("".equals(params.getCity()) || params.getCity()==null)){
            boolQuery.filter(QueryBuilders.termQuery("city", params.getCity()));
        }
        if (!("".equals(params.getBrand()) || params.getBrand()==null)){
            boolQuery.filter(QueryBuilders.termQuery("brand", params.getBrand()));
        }
        if (!("".equals(params.getStarName()) || params.getStarName()==null)){
            boolQuery.filter(QueryBuilders.termQuery("starName", params.getStarName()));
        }
		return boolQuery;
    }

    private static PageResult extracted(SearchResponse response) {
        SearchHits searchHits = response.getHits();
        long total = searchHits.getTotalHits().value;
        SearchHit[] hits = searchHits.getHits();
        List<HotelDoc> list = Arrays.stream(hits).map(item -> {
            String jsonStr = item.getSourceAsString();
            Object[] sortValues = item.getSortValues();
            HotelDoc hotelDoc = JSONObject.parseObject(jsonStr, HotelDoc.class);
            return hotelDoc;
        }).collect(Collectors.toList());
        return new PageResult(total, list);
    }
}

距离显示

要求:点击获取位置后,根据距离显示酒店,且要显示距离

思路:先判断有没有点击地图,如果携带了位置的请求就代表点击了地图,就需要根据坐标查询,且规定坐标先查找,可以保证在sort里value[0]就是坐标值

@Service
public class HotelService extends ServiceImpl<HotelMapper, Hotel> implements IHotelService {
    @Autowired
    private RestHighLevelClient client;
    private static Boolean isLocation = false;
    @Override
    public PageResult search(RequestParams params) throws IOException {
        SearchRequest request = new SearchRequest("hotel");
//        关键字搜索
        QueryBuilder query = buildBasicQuery(params);
        request.source().query(query);
//        分页
        int page = params.getPage();
        int size = params.getSize();
        request.source().from((page-1)*size).size(size);
//        排序
        String location = params.getLocation();
//        坐标排序
        if (!("".equals(location) || location==null)){
            GeoDistanceSortBuilder locationSort = SortBuilders.geoDistanceSort("location",new GeoPoint(location)).order(SortOrder.ASC).unit(DistanceUnit.KILOMETERS);
            request.source().sort(locationSort);
            FieldSortBuilder priceSort = SortBuilders.fieldSort("price").order(SortOrder.ASC);
            request.source().sort(priceSort);
            isLocation =true;
        }
//		  price/defult/socre排序        
        if (!("default".equals(params.getSortBy()))){
            FieldSortBuilder sortBy = SortBuilders.fieldSort(params.getSortBy());
            if ("price".equals(params.getSortBy())){
                sortBy.order(SortOrder.ASC);
            }else {
                sortBy.order(SortOrder.DESC);
            }
            request.source().sort(sortBy);
        }
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        return extracted(response);
    }

    private static QueryBuilder buildBasicQuery(RequestParams params) {
        String key  = params.getKey();
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
//        query
//        关键字搜索
        if ("".equals(key) || key==null){
            boolQuery.must(QueryBuilders.matchAllQuery());
        }else {
            boolQuery.must(QueryBuilders.matchQuery("all",key));
        }
//        过滤条件
        if (params.getMinPrice()!=null && params.getMaxPrice()!=null){
            boolQuery.filter(QueryBuilders.rangeQuery("price").gte(params.getMinPrice()).lte(params.getMaxPrice()));
        }
        if (!("".equals(params.getCity()) || params.getCity()==null)){
            boolQuery.filter(QueryBuilders.termQuery("city", params.getCity()));
        }
        if (!("".equals(params.getBrand()) || params.getBrand()==null)){
            boolQuery.filter(QueryBuilders.termQuery("brand", params.getBrand()));
        }
        if (!("".equals(params.getStarName()) || params.getStarName()==null)){
            boolQuery.filter(QueryBuilders.termQuery("starName", params.getStarName()));
        }
		return boolQuery;
    }

    private static PageResult extracted(SearchResponse response) {
        SearchHits searchHits = response.getHits();
        long total = searchHits.getTotalHits().value;
        SearchHit[] hits = searchHits.getHits();
        List<HotelDoc> list = Arrays.stream(hits).map(item -> {
            String jsonStr = item.getSourceAsString();
            Object[] sortValues = item.getSortValues();
            HotelDoc hotelDoc = JSONObject.parseObject(jsonStr, HotelDoc.class);
            if (sortValues.length>0 && isLocation){
                Object sortValue = sortValues[0];
                hotelDoc.setDistance(sortValue);
            }
            return hotelDoc;
        }).collect(Collectors.toList());
        return new PageResult(total, list);
    }
}

广告置顶

要求:广告置顶,有些广告需要在展示搜索结果的时候排在前面

思路:利用functionScore来做,但是functionScore是用不到bool的只能用普通的查询,在文档中维护一个字段叫isAD,在functions中过滤出isAD的文档,重新分配权重

@Service
public class HotelService extends ServiceImpl<HotelMapper, Hotel> implements IHotelService {
    @Autowired
    private RestHighLevelClient client;
    private static Boolean isLocation = false;
    @Override
    public PageResult search(RequestParams params) throws IOException {
        SearchRequest request = new SearchRequest("hotel");
//        关键字搜索
        QueryBuilder query = buildBasicQuery(params);
        request.source().query(query);
//        分页
        int page = params.getPage();
        int size = params.getSize();
        request.source().from((page-1)*size).size(size);
//        排序
        String location = params.getLocation();
        if (!("".equals(location) || location==null)){
            GeoDistanceSortBuilder locationSort = SortBuilders.geoDistanceSort("location",new GeoPoint(location)).order(SortOrder.ASC).unit(DistanceUnit.KILOMETERS);
            request.source().sort(locationSort);
            FieldSortBuilder priceSort = SortBuilders.fieldSort("price").order(SortOrder.ASC);
            request.source().sort(priceSort);
            isLocation =true;
        }
        if (!("default".equals(params.getSortBy()))){
            FieldSortBuilder sortBy = SortBuilders.fieldSort(params.getSortBy());
            if ("price".equals(params.getSortBy())){
                sortBy.order(SortOrder.ASC);
            }else {
                sortBy.order(SortOrder.DESC);
            }
            request.source().sort(sortBy);
        }
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        return extracted(response);
    }

    private static QueryBuilder buildBasicQuery(RequestParams params) {
        String key  = params.getKey();
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
//        query
//        关键字搜索
        if ("".equals(key) || key==null){
            boolQuery.must(QueryBuilders.matchAllQuery());
        }else {
            boolQuery.must(QueryBuilders.matchQuery("all",key));
        }
//        过滤条件
        if (params.getMinPrice()!=null && params.getMaxPrice()!=null){
            boolQuery.filter(QueryBuilders.rangeQuery("price").gte(params.getMinPrice()).lte(params.getMaxPrice()));
        }
        if (!("".equals(params.getCity()) || params.getCity()==null)){
            boolQuery.filter(QueryBuilders.termQuery("city", params.getCity()));
        }
        if (!("".equals(params.getBrand()) || params.getBrand()==null)){
            boolQuery.filter(QueryBuilders.termQuery("brand", params.getBrand()));
        }
        if (!("".equals(params.getStarName()) || params.getStarName()==null)){
            boolQuery.filter(QueryBuilders.termQuery("starName", params.getStarName()));
        }

//        广告置顶
        return QueryBuilders.functionScoreQuery(boolQuery, new FunctionScoreQueryBuilder.FilterFunctionBuilder[]{
                new FunctionScoreQueryBuilder.FilterFunctionBuilder(
                        QueryBuilders.termQuery("isAD",true),
                        ScoreFunctionBuilders.weightFactorFunction(10)
                )
        }).boostMode(CombineFunction.MULTIPLY);
    }

    private static PageResult extracted(SearchResponse response) {
        SearchHits searchHits = response.getHits();
        long total = searchHits.getTotalHits().value;
        SearchHit[] hits = searchHits.getHits();
        List<HotelDoc> list = Arrays.stream(hits).map(item -> {
            String jsonStr = item.getSourceAsString();
            Object[] sortValues = item.getSortValues();
            HotelDoc hotelDoc = JSONObject.parseObject(jsonStr, HotelDoc.class);
            if (sortValues.length>0 && isLocation){
                Object sortValue = sortValues[0];
                hotelDoc.setDistance(sortValue);
            }
            return hotelDoc;
        }).collect(Collectors.toList());
        return new PageResult(total, list);
    }
}

标签聚合

需求:从后台文档中获取实际数据,传入前端页面显示,且会动态变化,比如:选择了上海,就展示在上海的品牌,而不在上海的品牌就不显示

思路:先根据用户条件搜索文档,按照类别聚合

    @Override
    public Map<String, List<String>> filters(RequestParams requestParams){
        Map<String, List<String>> listMap = null;
        try {
            SearchRequest request = new SearchRequest("hotel");
//        查询条件构建
            searchAggs(request,requestParams);
            SearchResponse response = client.search(request, RequestOptions.DEFAULT);
            Aggregations aggregations = response.getAggregations();
            listMap = new HashMap<>();
            listMap.put("city",getList(aggregations, "getCity"));
            listMap.put("brand",getList(aggregations, "getBrand"));
            listMap.put("starName",getList(aggregations, "getStarName"));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return listMap;
    }

    private void searchAggs(SearchRequest request,RequestParams requestParams) {
        QueryBuilder queryBuilder = buildBasicQuery(requestParams);
        request.source().query(queryBuilder);
//        查询品牌
        request.source().aggregation(
                AggregationBuilders
                        .terms("getBrand")
                        .field("brand")
                        .size(20));
//        查询城市
        request.source().aggregation(
                AggregationBuilders
                        .terms("getCity")
                        .field("city")
                        .size(20));
//        查询星级
        request.source().aggregation(
                AggregationBuilders
                        .terms("getStarName")
                        .field("starName")
                        .size(20));
    }

    private List<String> getList(Aggregations aggregations, String name) {
        Terms getBrand = aggregations.get(name);
        List<String> list = new ArrayList<>();
        for (Terms.Bucket bucket : getBrand.getBuckets()) {
            String key = bucket.getKeyAsString();
            list.add(key);
        }
        return list;
    }

    private QueryBuilder buildBasicQuery(RequestParams params) {
        String key  = params.getKey();
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
//        query
//        关键字搜索
        if ("".equals(key) || key==null){
            boolQuery.must(QueryBuilders.matchAllQuery());
        }else {
            boolQuery.must(QueryBuilders.matchQuery("all",key));
        }
//        过滤条件
        if (params.getMinPrice()!=null && params.getMaxPrice()!=null){
            boolQuery.filter(QueryBuilders.rangeQuery("price").gte(params.getMinPrice()).lte(params.getMaxPrice()));
        }
        if (!("".equals(params.getCity()) || params.getCity()==null)){
            boolQuery.filter(QueryBuilders.termQuery("city", params.getCity()));
        }
        if (!("".equals(params.getBrand()) || params.getBrand()==null)){
            boolQuery.filter(QueryBuilders.termQuery("brand", params.getBrand()));
        }
        if (!("".equals(params.getStarName()) || params.getStarName()==null)){
            boolQuery.filter(QueryBuilders.termQuery("starName", params.getStarName()));
        }

//        广告置顶
        return QueryBuilders.functionScoreQuery(boolQuery, new FunctionScoreQueryBuilder.FilterFunctionBuilder[]{
                new FunctionScoreQueryBuilder.FilterFunctionBuilder(
                        QueryBuilders.termQuery("isAD",true),
                        ScoreFunctionBuilders.weightFactorFunction(10)
                )
        }).boostMode(CombineFunction.MULTIPLY);
    }

自动补全

需求:要求用户输入拼音,可以根据输入的拼音自动补全,例如:输入s自动补全 三,四,蛇

思路:利用分词器,在新增文档的时候,根据拼音分词器把品牌,地址做拆分,用户输入受字母的时候,后台根据首字符检索字段的拼音,要设计好拼音分词器的拆分条件

/**
 * 自动补全
 * @param key 补全前缀
 * @return 补全数组
 */
@Override
public List<String> suggestion(String key) {
    List<String> collect;
    try {
        SearchRequest request = new SearchRequest("hotel");
        request.source().suggest(new SuggestBuilder()
                .addSuggestion("mySuggestion",
                        SuggestBuilders
                                .completionSuggestion("suggestion")
                                .prefix(key)
                                .skipDuplicates(true)
                                .size(10)));
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        CompletionSuggestion mySuggestion = response.getSuggest().getSuggestion("mySuggestion");
        List<CompletionSuggestion.Entry.Option> options = mySuggestion.getOptions();
        collect = options.stream().map(item -> item.getText().string()).collect(Collectors.toList());
        System.err.println(collect);
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
    return collect;
}

构建索引库比较关键,这里把用不到的字段省略了,不然太冗余了

#hotel
PUT /hotel
{
  "mappings":{
    "properties":{
      "address":{
        "type": "keyword",
        "copy_to": "all"
      },
      "brand":{
        "type": "keyword",
        "copy_to": "all"
      },    
      "city":{
        "type": "keyword",
        "copy_to": "all"
      },
      "name":{
        "type": "text",
        "analyzer": "text_analyzere",
        "search_analyzer": "ik_smart",
        "copy_to": "all"
      },
      # all字段,用户确认搜索的时候用到的。analyzer代表新增文档的时候,按照text_analyzere这个分词器,根据最大粒度拆分,且用到了py拼音分词器。
      # search_analyzer,用户确认搜索的时候用这个分词器去拆分用户的输入信息
      "all":{
        "type": "text",
        "analyzer": "text_analyzere",
        "search_analyzer": "ik_max_word"
      },
      #suggestion专门为自动补全做的字段,类型只能是completion,completion是一个数组,数组内的字段只能是keyword不能拆分,因为如果拆分的话就有很多个值出来,keyword保证不可拆分,那么在同一个文档内这个suggestion是固定的,比如completion由品牌跟地址组成,品牌=如家,地址=北京,那这个分词器拆出来只能是:rujia/rj,beijing/bj,
      "suggestion":{
        "type": "completion",
        "analyzer": "completion_analyzere"
      }
    }
  },
  "settings": {
    "analysis": {
      "analyzer": {
      #text的分词器,新增文档的时候有些text字段可能搜索的时候需要用到。
        "text_analyzere":{
          "tokenizer":"ik_max_word",
          "filter":"py"
        },
      #completion的分词器
        "completion_analyzere":{
          "tokenizer":"keyword",
          "filter":"py"
        }
      },
      "filter": {
          "type": "pinyin", //类型
          "keep_full_pinyin": false,//当启用这个选项,如: 刘德华 >[ liu , de , hua ),默认值:真的
          "keep_joined_full_pinyin": true,//当启用此选项时,例如: 刘德华 >[ liudehua ],默认:false
          "keep_original": true,//当启用此选项时,将保留原始输入,默认值:false
          "limit_first_letter_length": 16,//set first_letter结果的最大长度,默认值:16
          "remove_duplicated_term": true,//当此选项启用时,重复项将被删除以保存索引,例如: de的 > de ,默认:false,注:职位相关查询可能会受到影响
          "none_chinese_pinyin_tokenize" :false //非中国字母分解成单独的拼音词如果拼音,默认值:true,如:liu , de , hua , a , li , ba , ba , 13 , zhuang , han ,注意: keep_none_chinese 和 keep_none_chinese_together 应该启用
      }
    }
  }
}

数据同步

利用mq实现数据同步

生产者

@PostMapping
public void saveHotel(@RequestBody Hotel hotel){
    Long i = 1L;
    hotel.setId(i);
    hotelService.save(hotel);
    String exchangeName = "topic.hotel";
    String key = "hotel.insert";
    rabbitTemplate.convertAndSend(exchangeName,key,hotel.getId());
    System.err.println("发送成功--->新增");
}

消费者

@Bean
public Queue queueInsert(){
    return new Queue("topic.insert.queue",true);
}
@Bean
public TopicExchange topicExchange(){
    return new TopicExchange("topic.hotel");
}
@Bean
public Queue queueDelete(){
    return new Queue("topic.delete.queue",true);
}
@Bean
public Binding bindingTopicBuilder(TopicExchange topicExchange,Queue queueInsert){
    return BindingBuilder.bind(queueInsert).to(topicExchange).with("hotel.insert");
}
@Bean
public Binding bindingTopicBuilder2(TopicExchange topicExchange,Queue queueDelete){
    return BindingBuilder.bind(queueDelete).to(topicExchange).with("hotel.delete");
}
@Component
public class ListenMq {
    @Autowired
    private IHotelService hotelService;
    @RabbitListener(queues = "topic.insert.queue")
    public void listenInsert(Long id){
        hotelService.updateById(id);
    }

    @RabbitListener(queues = "topic.delete.queue")
    public void listenDelete(Long id){
        hotelService.deleteById(id);
    }
}
@Override
public void updateById(Long id) {
    try {
        IndexRequest request = new IndexRequest("hotel").id(id.toString());
        Hotel hotel = this.getById(id);
        HotelDoc hotelDoc = new HotelDoc(hotel);
        String jsonString = JSON.toJSONString(hotelDoc);
        request.source(jsonString, XContentType.JSON);
        client.index(request, RequestOptions.DEFAULT);
        System.err.println("新增一条数据");
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
}

有关ES实战 | 黑马旅游案例的更多相关文章

  1. 使用canal同步MySQL数据到ES - 2

    文章目录一、概述简介原理模块二、配置Mysql使用版本环境要求1.操作系统2.mysql要求三、配置canal-server离线下载在线下载上传解压修改配置单机配置集群配置分库分表配置1.修改全局配置2.实例配置垂直分库水平分库3.修改group-instance.xml4.启动监听四、配置canal-adapter1修改启动配置2配置映射文件3启动ES数据同步查询所有订阅同步数据同步开关启动4.验证五、配置canal-admin一、概述简介canal是Alibaba旗下的一款开源项目,Java开发。基于数据库增量日志解析,提供增量数据订阅&消费。Git地址:https://github.co

  2. 「Python|Selenium|场景案例」如何定位iframe中的元素? - 2

    本文主要介绍在使用Selenium进行自动化测试或者任务时,对于使用了iframe的页面,如何定位iframe中的元素文章目录场景描述解决方案具体代码场景描述当我们在使用Selenium进行自动化测试的时候,可能会遇到一些界面或者窗体是使用HTML的iframe标签进行承载的。对于iframe中的标签,如果直接查找是无法找到的,会抛出没有找到元素的异常。比如近在咫尺的例子就是,CSDN的登录窗体就是使用的iframe,大家可以尝试通过F12开发者模式查看到的tag_name,class_name,id或者xpath来定位中的页面元素,会抛出NoSuchElementException异常。解决

  3. 微信小程序开发入门与实战(Behaviors使用) - 2

    @作者:SYFStrive @博客首页:HomePage📜:微信小程序📌:个人社区(欢迎大佬们加入)👉:社区链接🔗📌:觉得文章不错可以点点关注👉:专栏连接🔗💃:感谢支持,学累了可以先看小段由小胖给大家带来的街舞👉微信小程序(🔥)目录自定义组件-behaviors    1、什么是behaviors    2、behaviors的工作方式    3、创建behavior    4、导入并使用behavior    5、behavior中所有可用的节点    6、同名字段的覆盖和组合规则总结最后自定义组件-behaviors    1、什么是behaviorsbehaviors是小程序中,用于实现

  4. ES基础入门 - 2

    ES一、简介1、ElasticStackES技术栈:ElasticSearch:存数据+搜索;QL;Kibana:Web可视化平台,分析。LogStash:日志收集,Log4j:产生日志;log.info(xxx)。。。。使用场景:metrics:指标监控…2、基本概念Index(索引)动词:保存(插入)名词:类似MySQL数据库,给数据Type(类型)已废弃,以前类似MySQL的表现在用索引对数据分类Document(文档)真正要保存的一个JSON数据{name:"tcx"}二、入门实战{"name":"DESKTOP-1TSVGKG","cluster_name":"elasticsear

  5. ruby &&= 边缘案例 - 2

    有点边缘情况,但知道为什么&&=会这样吗?我正在使用1.9.2。obj=Object.newobj.instance_eval{@bar&&=@bar}#=>nil,expectedobj.instance_variables#=>[],soobjhasno@barinstancevariableobj.instance_eval{@bar=@bar&&@bar}#ostensiblythesameas@bar&&=@barobj.instance_variables#=>[:@bar]#whywouldthisversioninitialize@bar?为了比较,||=将实例变量初始

  6. 你真正了解什么是接口测试么?接口实战一“篇”入魂 - 2

    最近在工作中,看到一些新手测试同学,对接口测试存在很多疑问,甚至包括一些从事软件测试3,5年的同学,在聊到接口时,也是一知半解;今天借着这个机会,对接口测试做个实战教学,顺便总结一下经验,分享给大家。计划拆分成4个模块跟大家做一个分享,(接口测试、接口基础知识、接口自动化、接口进阶)感兴趣的小伙伴记得关注,希望对你的日常工作和求职面试,带来一些帮助。注:文章较长有5000多字,希望小伙伴们认真看完,当然有些内容对小白同学不是太友好,如果你需要详细了解其中的一些概念或者名词,请在文章之后留言,后续我将针对大家的疑问,整理输出一些大家感兴趣的文章。随着开发模式的迭代更新,前后端分离已不是新的概念,

  7. 关于ES集群信息的一些查看 - 2

    文章目录查看ES信息查看节点信息查看分片信息实际场景下ES分片及副本数量应该怎么分关于ES的灵活使用查看ES信息查看版本kibana:GET/查看节点信息GET/_cat/nodes?v解释:ip:集群中节点的ip地址;heap.percent:堆内存的占用百分比;ram.percent:总内存的占用百分比,其实这个不是很准确,因为buff/cache和available也被当作使用内存;cpu:cpu占用百分比;load_1m:1分钟内cpu负载;load_5m:5分钟内cpu负载;load_15m:15分钟内cpu负载;node.role:上图的dilmrt代表全部权限master:*代表

  8. linux查看es节点使用情况,elasticsearch(es) 如何查看当前集群中哪个节点是主节点(master) - 2

    elasticsearch查看当前集群中的master节点是哪个需要使用_cat监控命令,具体如下。查看方法es主节点确定命令,以kibana上查看示例如下:GET_cat/nodesv返回结果示例如下:ipheap.percentram.percentcpuload_1mload_5mload_15mnode.rolemastername172.16.16.188529952.591.701.45mdi-elastic3172.16.16.187329950.990.991.19mdi-elastic2172.16.16.231699940.871.001.03mdi-elastic4172

  9. FIFO实战学习-同步FIFO/异步FIFO-格雷码 - 2

    目录FIFO一.自定义同步FIFO1.1代码设计1.2Testbech1.3行为仿真***学习位宽计算函数$clog2()***$clog2()系统函数使用,可以不关注***分布式资源或者BLOCKBRAM二.异步FIFO2.1在FIFO判满的时候有两种方式:2.2异步FIFO为什么要使用格雷码2.2.1介绍格雷码2.2.2格雷码在异步FIFO中的应用2.2.2格雷码判满2.4二进制与格雷码之间的转换2.4.1二进制码转换为格雷码的方法2.4.2格雷码转换为二进制码的方法2.3实现框图2.5实现及仿真代码2.6仿真图验证2.7结论FIFO  这篇更多的是记录FIFO学习,参考了众多优秀的文章,

  10. ruby - 使用散列或案例陈述 [Ruby] - 2

    一般来说哪个更好用?:casenwhen'foo'result='bar'when'peanutbutter'result='jelly'when'stack'result='overflow'returnresult或map={'foo'=>'bar','peanutbutter'=>'jelly','stack'=>'overflow'}returnmap[n]更具体地说,什么时候应该使用案例陈述,什么时候应该只使用散列? 最佳答案 散列是一种数据结构,而case语句是一种控制结构。当你只是检索一些数据时,你应该使用散列(就像你

随机推荐