日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

es---elasticsearch-篇二:idea操作es,常用查询DSL

發(fā)布時間:2023/12/18 编程问答 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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"
          ? ? ? }
          ? ? }
          ? ]
          }
      • 2:
        • #按坐標(biāo)排序
          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:?
        • #按某坐標(biāo),周圍的酒店,距離降序排序
          #查詢的sort的值,是公里數(shù)
          #注意,如果排序,則打分為null
          GET /hotel/_search
          {
          ? "query":{
          ? ? "match_all": {}
          ? },
          ? "sort":[
          ? ? {
          ? ? ? "_geo_distance": {
          ? ? ? ? "location": {
          ? ? ? ? ? "lat": 30,
          ? ? ? ? ? "lon": 120
          ? ? ? ? },
          ? ? ? ? "order": "desc",
          ? ? ? ? "unit": "km"
          ? ? ? }
          ? ? }
          ? ]
          }
      • 分頁:默認(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"
          ? ? ? }
          ? ? }
          ? ]
          }

? ? ? ? ??#如果集群,:每臺機(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)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。