美文网首页
ES-查询搜索篇

ES-查询搜索篇

作者: 靈08_1024 | 来源:发表于2018-05-24 17:29 被阅读50次
    REST介绍

    REST(REpresentational State Transfer),字面意思为“表述性状态传输”,一种开发的约定。
    REST约定用HTTP的请求头POST、GET、PUT、DELETE正好对应CRUD(Create、Read、Update、Delete)四种数据操作。

    索引、映射的建立

    索引的建立:

    curl -X PUT http://localhost:9200/hospital/
    
    {
      "settings": {
        "number_of_shards": 1,//分片数量
        "number_of_replicas": 0//副本分片数量
      }
    }
    
    

    映射的建立:

    curl -X PUT http://localhost:9200/hospital/_mapping/medicine2?pretty
    
    {
        "dynamic": false,
        "properties": {
          "standardName": {
            "type": "text",
            "index": "analyzed"
          },
          "pattern": {
            "type": "text"
          },
         "validDate": {
            "type": "keyword"
          }
        }
    }
    

    1、DSL篇

    可以在java中输出SearchQueryBuilder,来查看对应的DSL(json格式)。

    在ES中进行查询,默认的分词器对于单个汉字都会进行分词,标点符号不计入分词,以空格来间隔英语单词。对于not_analyzed不计入分词器,只能全部搜索(或者用通配符查询、前缀查询)。对于计入分词的,term、match*(match系列)、querystring都支持,而且查询比较良好。keyword或者数字类型,都只支持整个匹配。

    说一说分页,分页都深度分页和游标分页。
    深度分页是每一次都会从最新的数据中进行查询。适合于实时查询分页。因为深度分页与CPU、IO、带宽、内存都有关。所以需要限制深度分页的页数,防止因为以上原因(或爬虫)造成卡顿或者宕机。
    游标分页是在你查询时,会初始化一个快照,在遍历时,从这个快照里取数据,也就是说,在初始化后对索引插入、删除、更新数据都不会影响遍历结果。适用于后端对于数据的大批量分析。

    2、JAVA篇

    以下所有的方法都写重点部分,需要样例,请参见GitHub:https://github.com/lingbao08/springboot-example.git

    1. 创建查询容器
    //此容器可以放置所有的queryBuilder
    BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
    
    1. 查询字符串
    //精确查询,查询有该分词的文档
    QueryBuilder termQuery = QueryBuilders.termQuery(field, value);
    //字符串查询,查询包含该分词的文档(英文只针对于单词,中文可能会拆开该词语:策略视分词器而定)
    QueryBuilder termQuery = QueryBuilders.queryStringQuery(value)
                 .field(field,2f);//可以指定单字段,也可以不指定,不指定按照默认字段查询
    //              .fields(map)//多个字段
    
    2.查询范围值
    //可以只选大于而不选小于。可以用于查询日期、数字、字符串等。
    //比较日期时注意和数据库格式一致
    //不包含的范围查询
    QueryBuilder range = QueryBuilders.rangeQuery(field).gt(0).lt(11);
    //包含的范围查询
    QueryBuilder range = QueryBuilders.rangeQuery(field).from(0).to(11);
    
    3.IN查询
    QueryBuilder terms = QueryBuilders.termsQuery("id", idList);
    
    2.多字段匹配单值
    MultiMatchQueryBuilder builder = QueryBuilders.multiMatchQuery(value, fields);
    
    3.单(多)字段匹配多值
    //构建匹配字段及其优先级
    Map<String,Float> map = new HashMap();
     int length = fields.length;
     for (int i = 0; i < length; i++) {
            map.put(fields[i],Float.valueOf(length-i));
     }
    //其中value中,eg:“A 神经 FFF” 表示这三个都搜索。
    QueryBuilder termQuery = QueryBuilders.queryStringQuery(value).fields(map);
    
    4.查询指定想要的字段(或不想要的字段)
    SearchRequestBuilder srb = esClient.prepareSearch(indexName)
                        .setFetchSource(shows, null);//关键方法,前面为想要的字段,后面为不想要的字段
    
    5.排序
    SortBuilder sort = SortBuilders.fieldSort(field).order(SortOrder.ASC);
    SortBuilders.scoreSort();//得分权重排序
    //多个排序可以按照顺序来添加
    SearchRequestBuilder srb = esClient.prepareSearch(indexName)
                        .addSort(defaultScoreSort()).addSort(sort);
    
    4.计总数
    ValueCountAggregationBuilder aggregation =
                        AggregationBuilders.count("count").field(field);
    SearchRequestBuilder sr = esClient.prepareSearch(indexName).addAggregation(aggregation);
    if (CollectionUtils.isNotEmpty(conditions))
          sr = sr.setQuery(builderQueries(conditions));
     SearchResponse response = sr.execute().get();
    ValueCount count = response.getAggregations().get("count");
    return count.getValue();
    
    6.分页

    在ES中分页有两种,一种是静态分页(又称游标分页),一种动态分页(又称深度分页)。

    具体采用哪种分页,请参考上面DSL部分
    动态分页

    SearchRequestBuilder srb = esClient.prepareSearch(indexName)
                        .setFrom(from).setSize(pageSize);
    

    静态分页(取自官网):

    SearchResponse scrollResp = esClient.prepareSearch(indexName)
                    .addSort(sort)
                    .setScroll(new TimeValue(60000))//search context存活时间
                    .setQuery(builderQueries(conditions))
                    .setFrom(from).setSize(pageSize).get(); //max of 100 hits will be returned for each scroll
            //Scroll until no hits are returned
            do {
                for (SearchHit hit : scrollResp.getHits().getHits()) {
                    //Handle the hit...
                }
    
                scrollResp = esClient.prepareSearchScroll(scrollResp.getScrollId()).setScroll(new TimeValue(60000)).execute().actionGet();
            }
            while (scrollResp.getHits().getHits().length != 0); // Zero hits mark the end of the scroll and the while loop.
    
    
    5.插入单条
    IndexResponse response = this.esClient.prepareIndex(indexName, typeName).setSource(objectMapper.writeValueAsBytes(t), XContentType.JSON).get();
    if (responses.status() == RestStatus.OK) return true;
    
    6.批量插入
    BulkRequestBuilder bulkRequestBuilder = this.esClient.prepareBulk();
    
     for (T t : list) {
            IndexRequestBuilder indexRequestBuilder = esClient.prepareIndex(indexName, typeName).setSource(objectMapper.writeValueAsBytes(t), XContentType.JSON);
            bulkRequestBuilder.add(indexRequestBuilder);
     }
    
    BulkResponse responses = bulkRequestBuilder.execute().actionGet();
    if (responses.status() == RestStatus.OK) return true;
    
    7.更新(单条)
    UpdateResponse response = this.esClient.prepareUpdate(indexName, typeName, esId)
                        .setDoc(objectMapper.writeValueAsBytes(t), XContentType.JSON).get();
    if (response.status() == RestStatus.OK) return true;
    
    8.删除
    BulkByScrollResponse response = DeleteByQueryAction.INSTANCE
                        .newRequestBuilder(esClient).source(indexName)
                        .filter(builderQueries(conditions)).get();
    

    参考链接:https://www.elastic.co/guide/en/elasticsearch/client/java-api/5.6/index.html

    中文分词

    参见优化篇——中文分词。

    分词包的使用

    最近正在破解搜狗的scel文件,loading。。。。。。

    相关文章

      网友评论

          本文标题:ES-查询搜索篇

          本文链接:https://www.haomeiwen.com/subject/zrciuxtx.html