es---elasticsearch-篇二:idea操作es,常用查询DSL
生活随笔
收集整理的這篇文章主要介紹了
es---elasticsearch-篇二:idea操作es,常用查询DSL
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
上一篇我們已經(jīng)寫到了對索引庫的操作,現(xiàn)在我們要更進(jìn)一步,對文檔document及后面的操作:
- 我們現(xiàn)在添加文檔到索引庫(相當(dāng)于MySQL添加一條記錄到table當(dāng)中)
- 我們新建立了一個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這里創(chuàng)建倒排索引}
- 剛剛我們測試了添加一條記錄。但是我們現(xiàn)在需要將MySQL當(dāng)中的hotel表的所有記錄導(dǎo)入hotel索引庫,那么我們需要建兩個實體類,一個對應(yīng)MySQL,一個對應(yīng)es索引庫,然后將兩個實體類進(jìn)行關(guān)聯(lián),從而將MySQL的hotel表和es的索引庫進(jìn)行關(guān)聯(lián)
- 首先我們創(chuàng)建對應(yīng)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數(shù)據(jù)庫,所以需要導(dǎo)入這兩個依賴
- <!--整合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>
- 然后建一個對應(yīng)hotel索引庫的實體類:(構(gòu)造函數(shù)location那里不一樣)
- 思路:我們是是將MySQL對應(yīng)的hotel實體類的對象作為參數(shù),傳進(jìn)索引庫的構(gòu)造方法里面來對索引庫對象對應(yīng)的屬性進(jìn)行初始化
- 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;/*經(jīng)緯度換成location*/private String location;private String pic;public HotelDoc() {}/*構(gòu)造函數(shù)*/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();/*緯度和經(jīng)度*/this.location = hotel.getLatitude()+","+hotel.getLongitude();this.pic = hotel.getPic();} }
- 然后寫hotelMapper,繼承BaseMapper
- 再寫hotelService,繼承苞米豆的IService
- 然后寫他的實現(xiàn)類,我們是繼承了mybatis-plus提供的ServiceImpl
- 緊接著我們寫service的測試類
- ?我們既然要注入es客戶端,那么我們?nèi)萜鳟?dāng)中就需要有這個es客戶端,所以我們?nèi)宇惻渲?#xff0c;并且將啟動類配置好掃描器:
- 掃描器:@MapperScan("com.pro.mapper")
- @Beanpublic RestHighLevelClient client(){return new RestHighLevelClient(RestClient.builder(HttpHost.create("http://192.168.8.171:9200")));}
- 既然要連接MySQL數(shù)據(jù)庫,那么我們需要去核心配置文件寫上我們的配置
- 數(shù)據(jù)庫連接四大金剛
- 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
- 執(zhí)行測試類之后,我們?nèi)ゲ橐幌率欠裼羞@個文檔記錄,
- source里面就是我們加進(jìn)來的內(nèi)容
- get /hotel/_doc/38665
-
那么我們查詢MySQL記錄并將其加入索引庫成功了!
-
有了增加,我們再來寫修改,刪除,查看以及批量增加
- 查單個
- /*根據(jù)id查出索引庫的文檔,強(qiáng)轉(zhuǎn)為對象輸出*/@Testpublic void testGetDocumentById() throws IOException {GetRequest request = new GetRequest("hotel", "38665");//發(fā)請求,得到響應(yīng)GetResponse response = client.get(request, RequestOptions.DEFAULT);String json = response.getSourceAsString();HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);System.out.println(hotelDoc);}
- 修改
- /*根據(jù)id修改索引庫對應(yīng)的文檔*/@Testpublic void testUpdateDocument(){//1.requestUpdateRequest request = new UpdateRequest("hotel", "38665");//修改request.doc("price","262","starName","三鉆");}
- 刪除
- /*根據(jù)id刪除索引庫對應(yīng)的文檔*/@Testpublic void TestDeleteDocumentById() throws IOException {//創(chuàng)建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);//將數(shù)據(jù)對象,一個個轉(zhuǎn)為json,加入到批量操作的對象request中request.add(new IndexRequest("hotel").id(hotelDoc.getId().toString()).source(JSON.toJSONString(hotelDoc),XContentType.JSON));}//發(fā)送請求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,我們可以進(jìn)行一個對比
- 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班');-- 五個聚合函數(shù) -- 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 后面只能跟分組的字段,聚合函數(shù)-- select classid,avg(age) from stu GROUP BY classid;-- 對所有記錄篩選 -- select * from stu where age < 20;-- 對組進(jìn)行篩選,使用having,后面只能跟分組的字段,聚合函數(shù) -- 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;-- 內(nèi)連接 兩邊協(xié)商,沒有的去取消,查出5條數(shù)據(jù) -- select * from stu s inner join class c on s.classid=c.classid;-- 左連接,以左為主,可以查6條數(shù)據(jù) -- select * from stu s left join class c on s.classid=c.classid;-- 右連接,以右為主,可以查5條數(shù)據(jù) -- select * from stu s right join class c on s.classid=c.classid;
- 常見的查詢類型:
- 查所有,match_all
- 全文檢索,可以利用分詞器對用戶輸入進(jìn)行分詞,再去倒排索引庫中取匹配
- match_query
- multi_match_query
- 精確查詢,一般是keyword,數(shù)值,日期,boolean,id,range,term
- 地理(geo)查詢,經(jīng)緯度查詢
- geo_distance
- geo_bounding_box
- 復(fù)合(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"]}} }#上面這兩種查詢結(jié)果是一樣的,因為這三個字段我們已經(jīng)copy_to all里面了,所以第一種顯然要好些
- match,multi_match的區(qū)別:后者可以搜多個字段
- #精準(zhǔn)查,term不分詞:例如查品牌
- #精準(zhǔn)查詢 term 特點:不分詞 GET /hotel/_search {"query":{"term":{"city":{"value": "上海"}}} }
- #范圍內(nèi)精準(zhǔn)查詢 range 特點:不分詞?
- gte:>=,? ? ? lte:<= #范圍內(nèi)精準(zhǔn)查詢 range 特點:不分詞 GET /hotel/_search {"query": {"range": {"price": {"gte": 100,"lte": 300}}} }
- term,range這兩種查詢:前者一般搜keyword,后者一般搜數(shù)值(在某個范圍內(nèi))
- #地理查詢,經(jīng)緯度查詢:geo_distance;? ?geo_bounding_box
- geo_distance:? 圓形范圍,根據(jù)范圍和經(jīng)緯度查
- #地理查詢,經(jīng)緯度查詢: #geo_distance:? 圓形范圍 GET /hotel/_search {"query":{"geo_distance":{"distance":"150km","location":"31.174377,121.442875"}} }
-
geo_bounding_box矩形范圍:lat緯度,lon經(jīng)度
- #geo_bounding_box矩形范圍:lat緯度,lon經(jīng)度 GET /hotel/_search {"query":{"geo_bounding_box":{"location":{"top_left":{"lat":31.1,"lon":121.5},"bottom_right":{"lat":30.9,"lon":121.7}}}} }
-
#復(fù)合查詢??
-
將簡單的查詢組合起來
-
算分函數(shù)查詢,function score ,可以控制文檔相關(guān)性算分,
-
控制文檔排名
-
1)function?score
先查所有all里面分詞有外灘的文檔,然后再過濾出brand為如家的品牌(精準(zhǔn)過濾),最后對對應(yīng)文檔的_score進(jìn)行操作??????
-
- filter:term精準(zhǔn)過濾出“如家”這個品牌(過濾出哪些文檔要加分)
- 算分函數(shù)
- weight:? 給一個常量值作為函數(shù)的結(jié)果:
- random_score 隨機(jī)生成一個值,作為函數(shù)結(jié)果
- script_score 自定義計算公式,公式結(jié)果作為函數(shù)結(jié)果
- field_score_factor 用文檔中的某個字段作為函數(shù)的結(jié)果
- 加權(quán)模式(boost_mode):定義function score 和 query score(查出的分值之間的運(yùn)算方式:默認(rèn)相乘)
- multiply:? 兩者相乘 (默認(rèn))
- replace:? 用算分函數(shù)替換查詢出來的分值
-
其它?:sum,avg,max,min
- #1)function?score先查所有all里面分詞有外灘的文檔, 然后再過濾出brand為如家的品牌(精準(zhǔn)過濾),最后對對應(yīng)文檔的_score進(jìn)行操作GET /hotel/_search {"query":{"function_score": {"query": {"match":{"all":"外灘"}},"functions": [{"filter": {"term":{"brand": "如家"}},"weight":10}],"boost_mode": "replace"}} }
-
復(fù)合查詢之布爾查詢
- 是一個或多個查詢子句的組合,子查詢的組合方式
- must? 必須匹配每個子查詢? &&
- should? 選擇性的匹配子查詢? ?||
- must_not 必須不匹配? ?,不參與算分
- filter? ?必須匹配,不參與算分
- #搜索如家,價格小于等于400,坐標(biāo)在31.2,121.5周圍十公里范圍內(nèi)的酒店 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}}}]}}} }
-
有了搜索結(jié)果之后,我們可以對搜索結(jié)果進(jìn)行排序(默認(rèn)是根據(jù)算分來排)
- 可以排序的字段類型:keyword,數(shù)值,地理坐標(biāo),日期
- 1:
- #排序,根據(jù)評分降序
GET /hotel/_search?
{
? "query":{
? ? "match_all": {}
? },
? "sort":[
? ? {
? ? ? "score":{
? ? ? ? "order":"desc"
? ? ? }
? ? }
? ]
}
- #排序,根據(jù)評分降序
- 2:
- #按坐標(biāo)排序
GET /hotel/_search
{
? "query":{
? ? "match_all": {}
? },
? "sort":[
? ? {
? ? ?"_geo_distance": {
? ? ? ?"location": "31.21,121.5",
? ? ? ?"order": "desc",
? ? ? ?"unit": "km"
? ? ?}
? ? }
? ]
}
- #按坐標(biāo)排序
- 3:
- #按分值排序,分值一致時,按價格升序
GET /hotel/_search
{
? "query":{
? ? "match_all": {}
? },
? "sort":[
? ? {
? ? ? "score":{
? ? ? ? "order": "desc"
? ? ? },
? ? ? "price": {
? ? ? ? "order": "asc"
? ? ? }
? ? }
? ]
}
?
- #按分值排序,分值一致時,按價格升序
- 4:?
- #按某坐標(biāo),周圍的酒店,距離降序排序
#查詢的sort的值,是公里數(shù)
#注意,如果排序,則打分為null
GET /hotel/_search
{
? "query":{
? ? "match_all": {}
? },
? "sort":[
? ? {
? ? ? "_geo_distance": {
? ? ? ? "location": {
? ? ? ? ? "lat": 30,
? ? ? ? ? "lon": 120
? ? ? ? },
? ? ? ? "order": "desc",
? ? ? ? "unit": "km"
? ? ? }
? ? }
? ]
}
- #按某坐標(biāo),周圍的酒店,距離降序排序
-
分頁:默認(rèn)的返回10條,from,size
- #分頁
#es 默認(rèn)的返回10條,from,size,我們現(xiàn)在分20條
GET /hotel/_search
{
? "query":{
? ? "match_all": {}
? },
? "from": 0,
? "size": 20,
? "sort":[
? ? {
? ? ? "price": {
? ? ? ? "order": "asc"
? ? ? }
? ? }
? ]
}
- #分頁
- 1:
? ? ? ? ??#如果集群,:每臺機(jī)器分配一些
????????#es的查新結(jié)果上限為10000條,超一條都會提示large
????????#但是有解決方案:after search (不支持隨機(jī)翻頁,我們有些APP,下拉分頁刷新,但是上劃沒有限制了,回不到上一頁
????????#scroll ?沒有查詢上限,內(nèi)存消耗大,es7.1之后,就不推薦用了 ?
?
- 練習(xí):搜索:價格在220以內(nèi)的酒店
- 按從小到大升序排列
- 取前五個酒店
- #練習(xí):搜索:價格在220以內(nèi)的酒店 #按從小到大升序排列 #取前五個酒店 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"}}} }
- 設(shè)定標(biāo)簽,不設(shè)定,標(biāo)簽默認(rèn)是em,搜索字段和高亮字段默認(rèn)必須匹配
-
搜索小結(jié)
- 結(jié)構(gòu):
- get /hotel/_search
- query
- from? ?size
- sort
- field,_geo_distance
- hight
總結(jié)
以上是生活随笔為你收集整理的es---elasticsearch-篇二:idea操作es,常用查询DSL的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Gmail:如何跟踪邮件阅读状态
- 下一篇: opengl 五角星画法 源代码