es---elasticsearch-篇二:idea操作es,常用查询DSL
生活随笔
收集整理的這篇文章主要介紹了
es---elasticsearch-篇二:idea操作es,常用查询DSL
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
上一篇我們已經寫到了對索引庫的操作,現在我們要更進一步,對文檔document及后面的操作:
- 我們現在添加文檔到索引庫(相當于MySQL添加一條記錄到table當中)
- 我們新建立了一個HotelDocumentTest測試類
- @Test//添加文檔到索引庫void testIndexDocument() throws IOException {//GET /hotel/_doc/1IndexRequest request = new IndexRequest("hotel").id("1");request.source("{\"name\":\"zs\",\"city\":\"長沙\"}",XContentType.JSON);client.index(request,RequestOptions.DEFAULT);//在index這里創建倒排索引}
- 剛剛我們測試了添加一條記錄。但是我們現在需要將MySQL當中的hotel表的所有記錄導入hotel索引庫,那么我們需要建兩個實體類,一個對應MySQL,一個對應es索引庫,然后將兩個實體類進行關聯,從而將MySQL的hotel表和es的索引庫進行關聯
- 首先我們創建對應MySQL的實體類
- @TableName("tb_hotel") public class Hotel {@TableId(type = IdType.AUTO)private Long id;private String name;private String address;private Integer price;private Integer score;private String brand;private String city;private String starName;private String business;private String latitude;private String longitude;private String pic; }
- 然后我們需要用到mybatis-plus來操作MySQL數據庫,所以需要導入這兩個依賴
- <!--整合mybatis-plus--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.49</version></dependency><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.0.5</version></dependency>
- 然后建一個對應hotel索引庫的實體類:(構造函數location那里不一樣)
- 思路:我們是是將MySQL對應的hotel實體類的對象作為參數,傳進索引庫的構造方法里面來對索引庫對象對應的屬性進行初始化
- public class HotelDoc {private Long id;private String name;private String address;private Integer price;private Integer score;private String brand;private String city;private String starName;private String business;/*經緯度換成location*/private String location;private String pic;public HotelDoc() {}/*構造函數*/public HotelDoc(Hotel hotel) {this.id = hotel.getId();this.name = hotel.getName();this.address = hotel.getAddress();this.price = hotel.getPrice();this.score = hotel.getScore();this.brand = hotel.getBrand();this.city = hotel.getCity();this.starName = hotel.getStarName();this.business = hotel.getBusiness();/*緯度和經度*/this.location = hotel.getLatitude()+","+hotel.getLongitude();this.pic = hotel.getPic();} }
- 然后寫hotelMapper,繼承BaseMapper
- 再寫hotelService,繼承苞米豆的IService
- 然后寫他的實現類,我們是繼承了mybatis-plus提供的ServiceImpl
- 緊接著我們寫service的測試類
- ?我們既然要注入es客戶端,那么我們容器當中就需要有這個es客戶端,所以我們去啟動類配置,并且將啟動類配置好掃描器:
- 掃描器:@MapperScan("com.pro.mapper")
- @Beanpublic RestHighLevelClient client(){return new RestHighLevelClient(RestClient.builder(HttpHost.create("http://192.168.8.171:9200")));}
- 既然要連接MySQL數據庫,那么我們需要去核心配置文件寫上我們的配置
- 數據庫連接四大金剛
- mybatis.xml文件掃描包的配置
- mapper別名配置
- 開啟駝峰命名
- #mysql spring.datasource.driver-class-name=com.mysql.jdbc.Driver spring.datasource.url=jdbc:mysql://192.168.8.171:3306/hotel spring.datasource.username=root spring.datasource.password=root#掃描包 mybatis-plus.mapper-locations=classpath:mapper/*.xml#別名 mybatis-plus.type-aliases-package=com.pro.domain#駝峰 mybatis-plus.configuration.map-underscore-to-camel-case=true
- 執行測試類之后,我們去查一下是否有這個文檔記錄,
- source里面就是我們加進來的內容
- get /hotel/_doc/38665
-
那么我們查詢MySQL記錄并將其加入索引庫成功了!
-
有了增加,我們再來寫修改,刪除,查看以及批量增加
- 查單個
- /*根據id查出索引庫的文檔,強轉為對象輸出*/@Testpublic void testGetDocumentById() throws IOException {GetRequest request = new GetRequest("hotel", "38665");//發請求,得到響應GetResponse response = client.get(request, RequestOptions.DEFAULT);String json = response.getSourceAsString();HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);System.out.println(hotelDoc);}
- 修改
- /*根據id修改索引庫對應的文檔*/@Testpublic void testUpdateDocument(){//1.requestUpdateRequest request = new UpdateRequest("hotel", "38665");//修改request.doc("price","262","starName","三鉆");}
- 刪除
- /*根據id刪除索引庫對應的文檔*/@Testpublic void TestDeleteDocumentById() throws IOException {//創建request對象DeleteRequest request = new DeleteRequest("hotel", "38665");//刪除文檔client.delete(request,RequestOptions.DEFAULT);}
- 批量增加
- /*將MySQL查出來的所有記錄加到索引庫* 批量操作* */@Testpublic void testBulkRequest() throws IOException {QueryWrapper queryWrapper = new QueryWrapper();List<Hotel> hotelList = hotelService.list(queryWrapper);BulkRequest request = new BulkRequest();for (Hotel hotel : hotelList) {HotelDoc hotelDoc = new HotelDoc(hotel);//將數據對象,一個個轉為json,加入到批量操作的對象request中request.add(new IndexRequest("hotel").id(hotelDoc.getId().toString()).source(JSON.toJSONString(hotelDoc),XContentType.JSON));}//發送請求client.bulk(request,RequestOptions.DEFAULT);}
-
es官方提供了基于json的DSL來查詢
- 地址:Query DSL | Elasticsearch Guide [8.4] | Elastic
- https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl.html
- 譯文地址
- https://www.kancloud.cn/apachecn/elasticsearch-doc-zh/1945172
- es提供了基于json的DSL來查詢
- ES的DSL類似于MySQL的SQL,我們可以進行一個對比
- select * from class;select * from stu;select * from stu where classid = 1;-- in 條件可以是一個或多個-- select * from stu where classid in (1); select * from stu where classid in (1,2);select * from stu where classid = (select classid from class where classname='1班');-- 五個聚合函數 -- select count(*) from stu;select avg(age) from stu;select sum(age) from stu;select max(age) from stu;select min(age) from stu;-- 分組查詢 select 后面只能跟分組的字段,聚合函數-- select classid,avg(age) from stu GROUP BY classid;-- 對所有記錄篩選 -- select * from stu where age < 20;-- 對組進行篩選,使用having,后面只能跟分組的字段,聚合函數 -- select classid,avg(age) from stu GROUP BY classid having avg(age) > 21;-- 溫哥華 -- select classid,avg(age) from stu where gender = '男' GROUP BY classid having avg(age) > 21;select * from stu,class;select * from stu,class where stu.classid=class.classid and stu.stuid=1;-- 內連接 兩邊協商,沒有的去取消,查出5條數據 -- select * from stu s inner join class c on s.classid=c.classid;-- 左連接,以左為主,可以查6條數據 -- select * from stu s left join class c on s.classid=c.classid;-- 右連接,以右為主,可以查5條數據 -- select * from stu s right join class c on s.classid=c.classid;
- 常見的查詢類型:
- 查所有,match_all
- 全文檢索,可以利用分詞器對用戶輸入進行分詞,再去倒排索引庫中取匹配
- match_query
- multi_match_query
- 精確查詢,一般是keyword,數值,日期,boolean,id,range,term
- 地理(geo)查詢,經緯度查詢
- geo_distance
- geo_bounding_box
- 復合(compound)查詢,可以將上面的查詢組織在一起,合并查詢
- bool
- function_score
- 查詢DSL的語法:
- #查詢dsl的語法 GET /hotel/_search {"query":{"查詢類型":{"FIELD":"TEXT"}} }
- 查所有:
- #查所有 GET /hotel/_search {"query":{"match_all":{}} }
- match查詢,會對用戶的輸入分詞,再到索引庫檢索
- #match查詢,會對用戶的輸入分詞,再到索引庫檢索 GET /hotel/_search {"query":{"match":{"all":"深圳如家"}} }#允許多個字段搜 ,字段越多,查詢性能越差 GET /hotel/_search {"query":{"multi_match":{"query":"深圳如家","fields": ["brand","name","business"]}} }#上面這兩種查詢結果是一樣的,因為這三個字段我們已經copy_to all里面了,所以第一種顯然要好些
- match,multi_match的區別:后者可以搜多個字段
- #精準查,term不分詞:例如查品牌
- #精準查詢 term 特點:不分詞 GET /hotel/_search {"query":{"term":{"city":{"value": "上海"}}} }
- #范圍內精準查詢 range 特點:不分詞?
- gte:>=,? ? ? lte:<= #范圍內精準查詢 range 特點:不分詞 GET /hotel/_search {"query": {"range": {"price": {"gte": 100,"lte": 300}}} }
- term,range這兩種查詢:前者一般搜keyword,后者一般搜數值(在某個范圍內)
- #地理查詢,經緯度查詢:geo_distance;? ?geo_bounding_box
- geo_distance:? 圓形范圍,根據范圍和經緯度查
- #地理查詢,經緯度查詢: #geo_distance:? 圓形范圍 GET /hotel/_search {"query":{"geo_distance":{"distance":"150km","location":"31.174377,121.442875"}} }
-
geo_bounding_box矩形范圍:lat緯度,lon經度
- #geo_bounding_box矩形范圍:lat緯度,lon經度 GET /hotel/_search {"query":{"geo_bounding_box":{"location":{"top_left":{"lat":31.1,"lon":121.5},"bottom_right":{"lat":30.9,"lon":121.7}}}} }
-
#復合查詢??
-
將簡單的查詢組合起來
-
算分函數查詢,function score ,可以控制文檔相關性算分,
-
控制文檔排名
-
1)function?score
先查所有all里面分詞有外灘的文檔,然后再過濾出brand為如家的品牌(精準過濾),最后對對應文檔的_score進行操作??????
-
- filter:term精準過濾出“如家”這個品牌(過濾出哪些文檔要加分)
- 算分函數
- weight:? 給一個常量值作為函數的結果:
- random_score 隨機生成一個值,作為函數結果
- script_score 自定義計算公式,公式結果作為函數結果
- field_score_factor 用文檔中的某個字段作為函數的結果
- 加權模式(boost_mode):定義function score 和 query score(查出的分值之間的運算方式:默認相乘)
- multiply:? 兩者相乘 (默認)
- replace:? 用算分函數替換查詢出來的分值
-
其它?:sum,avg,max,min
- #1)function?score先查所有all里面分詞有外灘的文檔, 然后再過濾出brand為如家的品牌(精準過濾),最后對對應文檔的_score進行操作GET /hotel/_search {"query":{"function_score": {"query": {"match":{"all":"外灘"}},"functions": [{"filter": {"term":{"brand": "如家"}},"weight":10}],"boost_mode": "replace"}} }
-
復合查詢之布爾查詢
- 是一個或多個查詢子句的組合,子查詢的組合方式
- must? 必須匹配每個子查詢? &&
- should? 選擇性的匹配子查詢? ?||
- must_not 必須不匹配? ?,不參與算分
- filter? ?必須匹配,不參與算分
- #搜索如家,價格小于等于400,坐標在31.2,121.5周圍十公里范圍內的酒店 GET /hotel/_search {"query":{"bool": {"must": [{"match": {"FIELD": "如家"}}],"must_not": [{"range": {"FIELD": {"gte": 400}}}],"filter": [{"geo_distance":{"distance":"10km","location":{"lat":31.21,"lon":121.5}}}]}}} }
-
有了搜索結果之后,我們可以對搜索結果進行排序(默認是根據算分來排)
- 可以排序的字段類型:keyword,數值,地理坐標,日期
- 1:
- #排序,根據評分降序
GET /hotel/_search?
{
? "query":{
? ? "match_all": {}
? },
? "sort":[
? ? {
? ? ? "score":{
? ? ? ? "order":"desc"
? ? ? }
? ? }
? ]
}
- #排序,根據評分降序
- 2:
- #按坐標排序
GET /hotel/_search
{
? "query":{
? ? "match_all": {}
? },
? "sort":[
? ? {
? ? ?"_geo_distance": {
? ? ? ?"location": "31.21,121.5",
? ? ? ?"order": "desc",
? ? ? ?"unit": "km"
? ? ?}
? ? }
? ]
}
- #按坐標排序
- 3:
- #按分值排序,分值一致時,按價格升序
GET /hotel/_search
{
? "query":{
? ? "match_all": {}
? },
? "sort":[
? ? {
? ? ? "score":{
? ? ? ? "order": "desc"
? ? ? },
? ? ? "price": {
? ? ? ? "order": "asc"
? ? ? }
? ? }
? ]
}
?
- #按分值排序,分值一致時,按價格升序
- 4:?
- #按某坐標,周圍的酒店,距離降序排序
#查詢的sort的值,是公里數
#注意,如果排序,則打分為null
GET /hotel/_search
{
? "query":{
? ? "match_all": {}
? },
? "sort":[
? ? {
? ? ? "_geo_distance": {
? ? ? ? "location": {
? ? ? ? ? "lat": 30,
? ? ? ? ? "lon": 120
? ? ? ? },
? ? ? ? "order": "desc",
? ? ? ? "unit": "km"
? ? ? }
? ? }
? ]
}
- #按某坐標,周圍的酒店,距離降序排序
-
分頁:默認的返回10條,from,size
- #分頁
#es 默認的返回10條,from,size,我們現在分20條
GET /hotel/_search
{
? "query":{
? ? "match_all": {}
? },
? "from": 0,
? "size": 20,
? "sort":[
? ? {
? ? ? "price": {
? ? ? ? "order": "asc"
? ? ? }
? ? }
? ]
}
- #分頁
- 1:
? ? ? ? ??#如果集群,:每臺機器分配一些
????????#es的查新結果上限為10000條,超一條都會提示large
????????#但是有解決方案:after search (不支持隨機翻頁,我們有些APP,下拉分頁刷新,但是上劃沒有限制了,回不到上一頁
????????#scroll ?沒有查詢上限,內存消耗大,es7.1之后,就不推薦用了 ?
?
- 練習:搜索:價格在220以內的酒店
- 按從小到大升序排列
- 取前五個酒店
- #練習:搜索:價格在220以內的酒店 #按從小到大升序排列 #取前五個酒店 GET /hotel/_search {"query": {"range": {"price": {"lte": 220}}},"from": 0,"size": 5,"sort": [{"price": {"order": "asc"}}] } ? ? ? ? ?
-
高亮顯示
?
- ?高亮,require_field_match表示:是否匹配搜索字段和高亮字段
- #高亮,require_field_match表示:是否匹配搜索字段和高亮字段 GET /hotel/_search {"query":{"match":{"all":"如家"}},"highlight": {"fields": {"name": {"require_field_match": "false"}}} }
- 設定標簽,不設定,標簽默認是em,搜索字段和高亮字段默認必須匹配
-
搜索小結
- 結構:
- get /hotel/_search
- query
- from? ?size
- sort
- field,_geo_distance
- hight
總結
以上是生活随笔為你收集整理的es---elasticsearch-篇二:idea操作es,常用查询DSL的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Gmail:如何跟踪邮件阅读状态
- 下一篇: opengl 五角星画法 源代码