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);

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM