elastic search2.3.1(3) 查詢語句拼接實戰termQuery ,matchQuery, boolQuery, rangeQuery, wildcardQuery


1,elastic search的服務安裝在本地192.168.25.101的虛擬機上,先啟動es的服務。在進行索引查詢之前,首先建立索引庫, 並向索引庫中添加測試的索引信息。執行以下的命令后:(1)創建了INDEX = store,TYPE = books的索引庫 (2) 向索引庫中添加了id=1,以及id=2 的兩條索引記錄。

curl -XPUT 'http://192.168.25.101:9200/store/books/1' -d '{
 "title": "Elasticsearch: The Definitive Guide",
 "name" : {
 "first" : "Zachary",
 "last" : "Tong"
 },
 "publish_date":"2015-02-06",
 "price":"49.99"
 }'

  

#在添加一個書的信息
 curl -XPUT 'http://192.168.25.101:9200/store/books/2' -d '{
 "title": "Elasticsearch Blueprints",
 "name" : {
 "first" : "Vineeth",
 "last" : "Mohan"
 },
 "publish_date":"2015-06-06",
 "price":"35.99"
 }'

(1) 索引添加完成后,可以通過curl命令查詢,上述索引是否添加成功。

 #在linux中通過curl的方式查詢
 curl -XGET 'http://192.168.25.101:9200/store/books/1'

 

2,構造termQuery對象進行字符的精確匹配查詢

項目中引用的maven依賴仍然是elasticsearch 2.3.5的jar 

(1) 下面是用es的termQuery對象構造查詢語句,精確查詢price = “35.99”的書籍信息。以下es查詢語句相當於 sql語句:select * from books where price = 35.99。下面的代碼中首先是獲取transportClient對象,之后構造searchRequestBuilder的對象, 然后通過searchRequestBuilder對象發送http請求進行查詢。下面代碼運行后打印出來的searchRequesrBuilder 的內容如下:

@Test
    public void termsearch() {
        TransportClient client = null;
        try {
            client = ESConnectFactory.getTransportClient("192.168.25.101");
            SearchRequestBuilder searchRequestBuilder = client.prepareSearch("store")
                    .setTypes("books")
                    .setQuery(QueryBuilders.termQuery("price", "35.99"));
            System.out.println(searchRequestBuilder);
            SearchHit[] hits = searchRequestBuilder.get().getHits().getHits();
            for(SearchHit hit : hits){
                System.out.println(hit.getSourceAsString());
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }
#代碼運行后,控制台打印出來的searchRequestBuilder對象
{
  "query" : {
    "term" : {
      "price" : "35.99"
    }
  }
}

(2) 其實借助上面的searchRequestBuilder對象,我們還可以用curl命令進行精確匹配查詢。兩者的查詢結果是一致的。如下:

curl -XGET 'http://192.168.25.101:9200/store/books/_search' -d '{
     "query" : {
     "term" : {
     "price" : "35.99"
     }
     }
     }'

 

3,通過termsQuery實現指定多個值進行精確匹配查詢

下面的代碼與上述termQuery代碼很相似,只有構造query對象時有不同的地方。我這邊這展示不同地方:,QueryBuilder.termsQuery()方法有好幾個重載的方法,第二參數可以傳入一個可變參數類型,也可以傳入一個集合類型。以下的es語句相當於sql 語句:select * from book where price in in ("35.99","49.99")

  SearchRequestBuilder searchRequestBuilder = client.prepareSearch("store")
                    .setTypes("books")
                    .setQuery(QueryBuilders.termsQuery("price", "35.99","49.99")) //傳入可變參數類型
 List<String> price = new ArrayList<>();
 price.add("35.99");
 price.add("49.99");
 SearchResponse response = client.prepareSearch("store")
                    .setTypes("books")
                    .setQuery(QueryBuilders.termsQuery("price", price))       // 傳入一個集合類型
                    .get();

(1) 其中searchRequestBuider打印出來如下:

{
  "query" : {
    "terms" : {
      "price" : [ "35.99", "49.99" ]
    }
  }
}  

(2)與java代碼等同的curl命令如下:

  curl -XGET 'http://172.16.0.14:9200/store/books/_search' -d '{
     "query" : {
     "terms" : {
     "price" : ["35.99", "49.99"]
     }
     }
     }'

 

4, boolQuery查詢

先構造boolQuery的對象,然后在boolQuery對象里面添加邏輯判斷條件。boolquery嵌套的條件有以下類型: (1) must: 條件必須滿足,相當於 and   (2) should: 條件可以滿足也可以不滿足,相當於 or (3) must_not: 條件不需要滿足,相當於 not。 以下的es語句相當於sql語句: SELECT * FROM books WHERE (price = 35.99 OR price = 49.99) AND (publish_date != "2016-02-06")

  SearchRequestBuilder searchRequestBuilder = client.prepareSearch("store")
                    .setTypes("books")
                    .setQuery(QueryBuilders.boolQuery()
                            .should(QueryBuilders.termQuery("price", "35.99"))
                            .should(QueryBuilders.termQuery("price", "49.99"))
                            .mustNot(QueryBuilders.termQuery("publish_date", "2016-02-06")));// Query
    

(1)searchRequestBuilder對象打印出來如下:

{
  "query" : {
    "bool" : {
      "must_not" : {
        "term" : {
          "publish_date" : "2016-02-06"
        }
      },
      "should" : [ {
        "term" : {
          "price" : "35.99"
        }
      }, {
        "term" : {
          "price" : "49.99"
        }
      } ]
    }
  }
}

 

5,嵌套查詢

(1)這次先確定sql語句的寫法,然后根據將確定的sql語句改寫成es的語法形式。sql語句如下: SELECT * FROM books WHERE price = "35.99" OR ( publish_date = "2016-02-06" AND price =
"49.99" ) ,先把上述的sql語句拆成兩部分 (1)price = "35.99" (2) publish_date = "2016-02-06" AND price = "49.99" ,這兩部分中間是用OR連接,拆分后各自用should連接。然后再將 AND 關鍵字兩邊拆開,各自用must連接。如下:

   SearchRequestBuilder searchRequestBuilder = client.prepareSearch("store")
                    .setTypes("books")
                    .setQuery(QueryBuilders.boolQuery()
                            .should(QueryBuilders.termQuery("price", "35.99"))
                            .should(QueryBuilders.boolQuery()
                                     .must(QueryBuilders.termQuery("price","49.99"))
                                     .must(QueryBuilders.termQuery("publish_date","2016-02-06"))));

(2)searchRequestBuilder 打印結果如下:

{
  "query" : {
    "bool" : {
      "should" : [ {
        "term" : {
          "price" : "35.99"
        }
      }, {
        "bool" : {
          "must" : [ {
            "term" : {
              "price" : "49.99"
            }
          }, {
            "term" : {
              "publish_date" : "2016-02-06"
            }
          } ]
        }
      } ]
    }
  }
}

 

6,rangeQuery范圍的過濾

在構造rangeQuery對象時,相應搜索的field不能是String類型的,需要的field是數值類型。所以我需要在原來的類型中新增一個int類型的field: pageSize, 新增一個索引文檔id = 3:

curl -XPUT 'http://192.168.25.101:9200/store/books/3' -d '{
 "title": "The third book",
 "name" : {
 "first" : "Zachary",
 "last" : "Tong"
 },
 "publish_date":"2018-02-06",
 "price":"49.99",
 "pageSize":200
 }'

(1) rangeQuery("pageSize").from(100).to(300), 過濾pageSize在 [100, 300]范圍內的數據,兩邊都是閉區間。

  SearchRequestBuilder searchRequestBuilder = client.prepareSearch("store")
                    .setTypes("books")
                    .setQuery(QueryBuilders.matchAllQuery())
                    .setPostFilter(QueryBuilders.rangeQuery("pageSize").from(100).to(300));
         

(2)rangeQuery("pageSize").gt(100).lt(300) , (great than 100, less than 300) 過濾pageSize在(100, 300)范圍內的數據,兩邊都是開區間。

rangeQuery("pageSize").gte(100).lte(300)  (great than or equal 100, less than or equals 300)  過濾pageSize在 [100, 300]范圍內的數據,兩邊都是閉區間。

 SearchRequestBuilder searchRequestBuilder = client.prepareSearch("store")
                    .setTypes("books")
                    .setQuery(QueryBuilders.matchAllQuery())
                    .setPostFilter(QueryBuilders.rangeQuery("pageSize").gt(100).lt(300));

(3) searchQueryBuilder的結構如下:

{
  "query" : {
    "match_all" : { }
  },
  "post_filter" : {
    "range" : {
      "pageSize" : {
        "from" : 100,
        "to" : 200,
        "include_lower" : true,
        "include_upper" : true
      }
    }
  }
}

 

7,模糊查詢匹配

(1) es也提供了sql中類似於like語句的模糊匹配查詢,通過wildcardQuery的語句來實現。

Implements the wildcard search query. Supported wildcards are <tt>*</tt>, which matches any character sequence (including the empty one), and <tt>?</tt>,which matches any single character. Note this query can be slow, as it needs to iterate over many terms. In order to prevent extremely slow WildcardQueries,a Wildcard term should not start with one of the wildcards <tt>*</tt> or <tt>?</tt>.

模糊匹配查詢有兩種匹配符,分別是" * " 以及 " ? ", 用" * "來匹配任何字符,包括空字符串。用" ? "來匹配任意的單個字符。當文檔對象很多時,它需要遍歷查詢,用模糊搜索的查詢速度會 很慢 。最好不要用* 或者 ? 當做查詢的開頭字母,這種情況下速度會更加慢。

下面是搜索price是3開頭的文檔:(注意全文檢索的字段,不能用模糊搜索去匹配,測試時全文搜索字段用模糊查詢查詢不到結果)

 SearchRequestBuilder searchRequestBuilder = client.prepareSearch("store")
                    .setTypes("books")
                    .setQuery(QueryBuilders.wildcardQuery("price", "3*"));// Query
         

 searchRequestBuilder 具體結構如下:

{
  "query" : {
    "wildcard" : {
      "price" : "3*"
    }
  }
}

  

8,matchQuery用於文本類型字段的搜索

matchQuery會將搜索條件按照標准分詞器的規則分詞,分完詞之后分別搜索匹配項。(注意:  測試中全文檢索字段如果用termQuery 或者 wildcardQuery 將不能查詢成功。因為全文索引字段建立索引時已經被分詞工具分成單個單詞了)

(1)下面的代碼搜索時,先將"The third"關鍵字進行分詞,分成"The" 和"third" 然后分別和文檔中title分詞后的結果進行匹配。最終結果會匹配到 title= " Elasticsearch: The Definitive Guide" 以及 title ="The third book"的這兩條記錄。

  SearchRequestBuilder searchRequestBuilder = client.prepareSearch("store")
                    .setTypes("books")
                    .setQuery(QueryBuilders.matchQuery("title", "The third"));// Query
       

 searchRequestBuilder 對象的具體結構如下:

{
  "query" : {
    "match" : {
      "title" : {
        "query" : "The thrid",
        "type" : "boolean"
      }
    }
  }
}

  


免責聲明!

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



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