zoukankan      html  css  js  c++  java
  • elasticsearch查询

    elasticsearch官方API

    https://www.elastic.co/guide/en/elasticsearch/client/java-api/current/index.html

    一、restful api查询

    1.1、查询订单

    POST order/_search?q=P201903230001

    1.2、更新订单

    POST order / area / 1 / _update {
        "doc": {
            " price": "5",
            "payee": "tom"
        }
    }

    1.3、删除订单(删除order索引/库)

    DELETE order

    1.4、增加订单

    POST order / area / 1
    {
        " price": "5",
        "payee": "tom"
    }

    1.5、查询索引数据,或者索引下某类型数据

    1、 GET /lib/user/_search
    : 查询lib索引下的user类型的全部数据
    
    2、 GET /lib/_search
    :查询lib索引下的全部类型的数据
    
    3、 GET /_search
    :查询全部索引下的数据

    二、DSL格式理解

    2.1、DSL查询语句属性值是json数组还是json,取决于你条件是多个还是单个。 JSON数据格式灵活性

    一个条件时候可以用json
    must:{
       "match": { "title": "Search" }
    }
    
    多个条件时候可以用json数组
    must:[
       { "match": { "title": "Search" }},
       { "match": { "content": "Elasticsearch" }}
    ]

    三、Query DSL

     Elasticsearch 提供了一个完整的 query DSL,并且是 JSON 形式的

    叶子查询语句(Leaf Query):用于查询某个特定的字段,如 match , term 或 range 等

    复合查询语句 (Compound query clauses):用于合并其他的叶查询或复合查询语句,也就是说复合语句之间可以嵌套,用来表示一个复杂的单一查询

     3.1、查询order索引下所有数据

    GET order / area / _search {
        "query": {
            "match_all": {}
        }
    }

     3.2、分词查询:订单、多小、商品,包含这三个词中的一个或多个的文档就会被搜索出来

    GET / _search {
        "query": {
            "match": {
                "content": {
                    "query": "我的订单有多小种类商品"
                }
            }
        }
    }

    3.3、分词查询:订单、多小、商品,包含这三个词中的文档就会被搜索出来。

    match与match_phrase区别:match_phrase匹配到所有分词才能查询出来

    GET / _search {
        "query": {
            "match_phrase": {
                "content": {
                    "query": "我的订单有多小种类商品"
                }
            }
        }
    }

    3.4、多字段匹配

    GET order / area / _search {
        "query": {
            "multi_match": {
                "query": "this is a test",
                "fields": ["subject", "message"]
            }
        }
    }

     3.5、完全匹配

    GET order / area / _search {
        "query": {
            "term": {
                "NUM": "P201903230001"
            }
        }
    }

    3.6、逻辑运算

    6.3 逻辑运算
    如果有多个搜索关键字, Elastic 认为它们是or关系。
    
    
    $ curl 'localhost:9200/accounts/person/_search'  -d '
    {
      "query" : { "match" : { "desc" : "软件 系统" }}
    }'
    上面代码搜索的是软件 or 系统。
    
    如果要执行多个关键词的and搜索,必须使用布尔查询。
    
    
    $ curl 'localhost:9200/accounts/person/_search'  -d '
    {
      "query": {
        "bool": {
          "must": [
            { "match": { "desc": "软件" } },
            { "match": { "desc": "系统" } }
          ]
        }
      }
    }'

    3.7、range范围查询。下面查询出订单销售在100-200之间数据

    GET order/area/_search
    {
      "query":{
        "bool": {
          "must": [
            {
              "range": {
                "sales": {
                  "from": 100,
                  "to": null
                }
              }
            },
             {
              "range": {
                "sales": {
                  "from": null,
                  "to": 200
                }
              }
            }
          ]
        }
      }
    }
    
    或
    
    GET order/area/_search
    {
      "query":{
        "bool": {
          "must": [
            {
              "range": {
                "sales": {
                  "from": 100,
                  "to": 200
                }
              }
            }
          ]
        }
      }
    }

    3.8、term精确匹配

    3.8.1、term精确匹配:对字段进行确切值(exact value)的查询,如数字、时间、bool、not_analyzed字段等。

    3.8.2、注意:使用term要确定的是这个字段是否“被分析”(analyzed),默认的字符串是被分析的。字段被分析将查询不出内容尽管字符串完全匹配

    3.8.3、为什么有时候使用term查不出数据? 只是string类型才查不出,其它类型是可以的。

    原因:字段被分析将查询不出内容尽管字符串完全匹配。需要修改成:index:not_analyzed:将字段的原始值放入索引中,作为一个独立的term,它是除string字段以外的所有字段的默认值。

    注意:在 elasticsearch2.x 版本,字符串数据只有string类型。ES更新到5版本后,取消了 string 数据类型,代替它的是 keyword 和 text 数据类型

    官方解析

    Add the field value to the index unchanged, as a single term. This is the default for all fields that support this option except for string fields. not_analyzed fields are usually used with term-level queries for structured search.

    GET /megacorp/employee/_search
    {
      "query" :{
        "bool": {
           "must" : [
            {"term" : {"NAME":"我是小明"}}
            ]
        }
      }
    }

    实践:1:

    只有分词完全匹配、完全匹配、完全匹配“大白菜”这三个字后才可以返回数据。JAVA程序中采用QueryBuilders类的termQuery(String name, Object value)方法。

    GET /my_index/ny_type/_search
    {
      "query":{
        "term":{
          "productName":"大白菜"
        }
      }
    }

    实践2:

    第一次使用"term":{"productName":"大白菜" } 没返回数据觉得很疑惑。明明存在数据“今天大白菜很新鲜” ,确没匹配到任何数据。

    原因:productName字段type=text并且使用默认分词器,大白菜 => [大,白,菜]。分词后变成3个字,而term查询需要完全匹配“大白菜”,大白菜作1个分词去匹配查找数据。

    所以最后没有数据返回。

    GET /my_index/ny_type/_search
    {
      "query":{
        "term":{
          "productName":"大白菜"
        }
      }
    }

    3.8.4、字段text类型,怎样可以使用term精确查询? 

    3.8.4.1. text类型:会分词,先把对象进行分词处理,然后再再存入到es中。

    当使用多个单词进行查询的时候,当然查不到已经分词过的内容!

    3.8.4.2. keyword:不分词,没有把es中的对象进行分词处理,而是存入了整个对象! 这时候当然可以进行完整地查询!默认是256个字符!

    {
        "mapping": {
            "my_type": {
                "properties": {
                    "title": {
                        "type": "text",
                        "fields": {
                            "keyword": {
                                "type": "keyword",
                                "ignore_above": 256
                            }
                        }
                    }
                }
            }
        }
    GET my_index/my_type/_search
    {
      "query":{
            "term": {
                    "title.keyword": "elasticsearch is good"
                }
      }
    }

    3.9、terms多词精确匹配

    sql中的in:
    select * from tbl where col in ("value1", "value2")
    
    sql中的in,在elasticsearch使用terms实现
    term: {"field": "value"}
    terms: {"field": ["value1", "value2"]}

    3.10、Bool Query

    使用must语法,bool必须加上

    我们可以在查询条件中使用AND/OR/NOT操作符,这就是布尔查询(Bool Query)。布尔查询可以接受一个must参数(等价于AND),一个must_not参数(等价于NOT),以及一个should参数(等价于OR)。比如,我想查询about中出现music或者climb关键字的员工,员工的名字是John,但姓氏不是smith,我们可以这么来查询:

    GET /megacorp/employee/_search
    {
        "query": {
            "bool": {
                    "must": {
                        "bool" : { 
                            "should": [
                                { "match": { "about": "music" }},
                                { "match": { "about": "climb" }} ] 
                        }
                    },
                    "must": {
                        "match": { "first_nale": "John" }
                    },
                    "must_not": {
                        "match": {"last_name": "Smith" }
                    }
                }
        }
    }
    
    
    GET /megacorp/employee/_search
    {
      "query" :{
        "bool": {
           "must" : [
            {"match" : {"NAME":"我是小明"}},
            {"match" : {"INTEREST":"足球"}}
            ]
        }
      }
    }

     3.10.1、Bool Query语法

    bool过滤:用来合并多个过滤条件的查询结果的布尔逻辑,必须包含must和should中的一个或多个。它包含以下一些操作
    
    must: 相当于and
    must_not: 相当于 not
    should: 相当于or(连接多个匹配条件,列表形式)
    
    {
       "query": {
           "bool":{
               "must":{   //and age==50
                   "term":{"age":50} 
               },
               "must_not":{    //not date=2014-09-01
                   "term":{"date": "2014-09-01"} 
               },
               "should":[  //  _id==8 or _id=9  (举的不太恰当)
                   {"term":{"_id":8}},
                   {"term":{"_id":19}}
               ]
           }
       }
    }
    
    
    下面错误语法。bool里面只能有must,must_not,should等相同单词只能出现一次。
    {
       "query": {
           "bool":{
               "must":{   //and age==50
                   "term":{"age":50} 
               },
               "must":{   //and firstName==jack
                   "term":{"firstName":"jack"} 
               }
               "must_not":{    //not date=2014-09-01
                   "term":{"date": "2014-09-01"} 
               },
               "should":[  //  _id==8 or _id=9  (举的不太恰当)
                   {"term":{"_id":8}},
                   {"term":{"_id":19}}
               ]
           }
       }
    }

    3.11、处理 Null 值:exists/missing

    exists/missing作用:用来查找某个字段是否有值, 类似SQL中的 not is_null/is_null

    它返回某个特定有值字段的文档,用 SQL 的话就是用 IS NOT NULL 非空进行查询:
    SELECT tags FROM posts WHERE  tags IS NOT NULL
    
    GET /my_index/posts/_search
    {
        "query" : {
            "constant_score" : {
                "filter" : {
                    "exists" : { "field" : "tags" }
                }
            }
        }
    }
    
    
    这个 missing 查询本质上与 exists 恰好相反: 它返回某个特定 _无_ 值字段的文档,与以下 SQL 表达的意思类似:
    SELECT tags FROM posts WHERE  tags IS NULL
    
    GET /my_index/posts/_search
    {
        "query" : {
            "constant_score" : {
                "filter": {
                    "missing" : { "field" : "tags" }
                }
            }
    }

    3.12、检查语法是否正确

    GET my_index/my_type/_validate/query?explain

    3.13、multi_match多字段匹配查询

    //查询title,content包含elasticsearch
    GET /website/article/_search
    {
      "query": {
        "multi_match": {
          "query": "elasticsearch",
          "fields": ["title","content"]
        }
      }
    }

    3.14、filter使用

    //查找书名包含elasticsearch,并且价格在100-200之间
    GET book/area/_search
    {
      "query": {
        "bool": {
          "must": [
            {"match": {
              "name": "elasticsearch"
            }}
          ],
          "filter": {
            "range": {
              "price": {
                "gt": 100,
                "lt": 200
              }
            }
          }
        }
      }
    }

    3.15、编写高亮检索代码 

    public void highlightSearch() throws ParseException {  
        //创建加载配置文件的客户端工具,用来检索文档,单实例多线程安全  
        ClientInterface clientUtil = ElasticSearchHelper.getConfigRestClientUtil(mappath);  
        //设定查询条件,通过map传递变量参数值,key对于dsl中的变量名称  
        //dsl中有三个变量  
        //        condition  
        //        startTime  
        //        endTime  
        Map<String,Object> params = new HashMap<String,Object>();  
      
        DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
        //设置时间范围,时间参数接受long值  
        params.put("startTime",dateFormat.parse("2017-09-02 00:00:00"));  
        params.put("endTime",new Date());  
        params.put("condition","喜欢唱歌");//全文检索条件,匹配上的记录的字段值对应的匹配内容都会被高亮显示  
        //执行查询,demo为索引表,_search为检索操作action  
        ESDatas<Demo> esDatas =  //ESDatas包含当前检索的记录集合,最多1000条记录,由dsl中的size属性指定  
                clientUtil.searchList("demo/_search",//demo为索引表,_search为检索操作action  
                        "testHighlightSearch",//esmapper/demo.xml中定义的dsl语句  
                        params,//变量参数  
                        Demo.class);//返回的文档封装对象类型  
        //获取总记录数  
        long totalSize = esDatas.getTotalSize();  
        System.out.println(totalSize);  
        //获取结果对象列表,最多返回1000条记录  
        List<Demo> demos = esDatas.getDatas();  
        for(int i = 0; demos != null && i < demos.size(); i ++){//遍历检索结果列表  
            Demo demo = demos.get(i);  
            //记录中匹配上检索条件的所有字段的高亮内容  
            Map<String,List<Object>> highLights = demo.getHighlight();  
            Iterator<Map.Entry<String, List<Object>>> entries = highLights.entrySet().iterator();  
            while(entries.hasNext()){  
                Map.Entry<String, List<Object>> entry = entries.next();  
                String fieldName = entry.getKey();  
                System.out.print(fieldName+":");  
                List<Object> fieldHighLightSegments = entry.getValue();  
                for (Object highLightSegment:fieldHighLightSegments){  
                    /** 
                     * 在dsl中通过<mark></mark>来标识需要高亮显示的内容,然后传到web ui前端的时候,通过为mark元素添加css样式来设置高亮的颜色背景样式 
                     * 例如: 
                     * <style type="text/css"> 
                     *     .mark,mark{background-color:#f39c12;padding:.2em} 
                     * </style> 
                     */  
                    System.out.println(highLightSegment);  
                }  
            }  
        }  
    }  

     3.15、wildcard通配符查询,中文只能支持关键字查询,即只支持 type=keywork

    #有数据返回,wildcard只支持type=keyword
    GET /my_index/my_type/_search{
      "query": {
        "wildcard": {"name.keyword":"*标准化*"}
      }
    }
    
    #没数据返回,wildcard只支持type=keyword
    GET /my_index/my_type/_search{
      "query": {
        "wildcard": {"name":"*标准化*"}
      }
    }  

     3.16、Scroll深度分页或者返回大量数据或返回满足条件的所有数据

    --第一次查询
    GET /test_index/test_type/_search?scroll=1m { "query": { "match_all": {} } } --第二次查询 --注意:第二次查询就不需要索引了,但需要上次查询返回的_scroll_id作为本次的查询条件
    GET
    /_search/scroll { "scroll" : "1m", "scroll_id" : "dGNoBQAADnF1ZXJ5VGhlbkZldGNoBQAA"
    }

    四、分词

    4.1、elasticsearch_analysis_ik分词插件

    安装方式:解压后复制到elasticsearch_home/plugins/ik(这名字随便命名)

    POST _analyze
    {
    "analyzer":"ik_smart",
    "text":"我是中国人"
    }
    
    #分词结果:我,是,中国人
    
    
    POST _analyze
    {
    "analyzer":"ik_max_word",
    "text":"我是中国人"
    }
    
    #分词结果:我,是,中国,中国人

     4.2、全文搜索疑惑,输入了关键字,而且关键字的数据也存在,但搜索不到数据,为什么?

    GET / _search {
        "query": {
            "match": {
                "content": {
                    "query": "名字"
                }
            }
        }
    }

    #数据:我的名字叫李四
    #搜索关键字:名字
    #使用默认分词器,分词结果:我,的,名,字,叫,李,四
    #搜索结果:搜索不到结果
    #原因分析:
    因为使用默认分词器每个字是一个索引,如果使用IK分词器就能搜索到了。所有能不能搜索到是看分词结果。
    
    

     4.3、elasticsearch api 查看分词器分词结果

    public static void main(String[] args) {
    
            TransportClient client = EsUtils.getSingleClient();
    
            AnalyzeRequest analyzeRequest = new AnalyzeRequest("bbb")
                    .text("中华人民共和国国歌")
                    .analyzer("standard");
    
            List<AnalyzeResponse.AnalyzeToken> tokens = client.admin().indices()
                    .analyze(analyzeRequest)
                    .actionGet()
                    .getTokens();
    
            for (AnalyzeResponse.AnalyzeToken token : tokens) {
                System.out.println(token.getTerm());
            }
        }


    结果:
    中
    华
    人
    民
    共
    和
    国
    国
    歌
     

     4.4、prepareSearch查询,setQuery(QueryBuilders queryBuilders)设置查询条件

    public void pageQuery(){
    SearchRequestBuilder setQuery = preBuiltTransportClient.prepareSearch("index").setTypes("type")
    .setQuery(QueryBuilders.matchAllQuery())
    .addSort("id", SortOrder.ASC)
    .setFrom(0)
    .setSize(10);

    // 从第几条开始,查询多少条
    /* SearchResponse response = setQuery.setFrom(0).setSize(2).get(); */

    SearchResponse response = setQuery.get();

    SearchHits searchHits = response.getHits();
    System.out.println("一共的记录数: " + searchHits.getTotalHits());

    Iterator<SearchHit> iterator = searchHits.iterator();
    while (iterator.hasNext()){
    SearchHit searchHit = iterator.next();
    System.out.println(searchHit.getSourceAsString());
    }
    }

    4.5、Search + SearchSourceBuilder,SearchSourceBuilder存放查询条件和分页数据

    public void pageQueryAll(String pageNo,String pageSize){
            SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder().query(new MatchAllQueryBuilder()).from(0).size(20);
    
            SearchRequest searchRequest = new SearchRequest().indices("my_index").types("my_type").source(searchSourceBuilder);
    
            SearchResponse searchResponse = preBuiltTransportClient.search(searchRequest).actionGet();
    
            long totalHits = searchResponse.getHits().getTotalHits();
    
            SearchHits searchHits = searchResponse.getHits();
    
            Iterator<SearchHit> iterator = searchHits.iterator();
    
            while (iterator.hasNext()){
                SearchHit searchHit = iterator.next();
                System.out.println(searchHit.getSourceAsString());
            }
    
        }

     4.6、prepareSearch与search使用

    1、prepareSearch查询条件对象QueryBuilder
    preBuiltTransportClient.prepareSearch.setQuery(QueryBuilder queryBuilder);
    
    2、search SearchSourceBuilder查询条件对象QueryBuilder
    SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder().query(QueryBuilder queryBuilder);
    SearchRequest searchRequest = new SearchRequest().indices("index").types("type").source(searchSourceBuilder);
    preBuiltTransportClient.search(SearchRequest searchRequest);
  • 相关阅读:
    Win32编程day11 学习笔记
    Win32编程day06 学习笔记
    Win32编程day15 学习笔记
    Win32编程day12 学习笔记
    Win32编程day09 学习笔记
    Win32编程day07 学习笔记
    Win32编程day10 学习笔记
    生命周期
    组件中的data为什么不是一个对象而是一个函数?
    asp.net Request.ServerVariables 各参数说明集合
  • 原文地址:https://www.cnblogs.com/chenweichu/p/10582530.html
Copyright © 2011-2022 走看看