ElasticSearch第二章(ES8.X的使用)

目录

1:ES的使用(DSL创建索引库-相当于表)

1.1:什么是索引库

1.2:索引库的增删改查使用

2:ES的使用(DSL操作文档-相当于数据)

2.1:什么是文档

2.2:文档的增删改查

3:java代码开发

3.1:准备工作

3.2:代码操作索引(也就是表的增删改查)

3.3:代码操作文档(也就是数据的增删改查)

4:DSL实现复杂的查询

4.1:DSL对单个字段的查询

4.2:DSL对多个字段的查询

5:java代码复杂查询

5.1:Java代码简单查询

5.2:Java代码复杂查询


1:ES的使用(DSL创建索引库-相当于表)

这些都是在kibana的开发者工具中测试的curl的DSL语句,因为ES是RESTFul风格的,这里使用kibana工具测试

1.1:什么是索引库

这里的索引库就是相当于mysql的表创建

es01 就是相当于mysql数据库中的表,

mapping:就是对表中字段的映射,

properties:就是包含各个字段,

type:设置字段类型,包含字符类型、数字类型、布尔类型等

analyzer:设置字段的分词,创建倒排索引,便于搜索,只是用text类型

1.2:索引库的增删改查使用

索引库相当于创建了表,设置了各个字段的属性,索引。这是对于mysql来说的,便于理解

下边还有对索引库的数据的增删改查,就会看的更加清楚

#创建索引库名字 /es01 

#age字段     不用创建分词
#info字段       ik_smart创建分词
#email字段      keyword 不用创建分词
#name字段      前置名字 后置名字

put /es01
{
  "mappings":{
    
    "properties":{
      
      "age":{
        "type": "integer"
      },
      
      "info":{
        "type":"text",
        "analyzer":"ik_smart"
      },
      
      "email":{
        "type":"keyword",
        "index":false
      },
      
      "name":{
        "type":"object",
        "properties":{
          
          "firstName":{
            "type":"keyword",
            "index":false
            },
          "lastName":{
            "type":"keyword"
            }
        }
      }
      
    }
  }
}

#查询索引库
get /es01

#修改索引库 索引库只能添加新的字段
#添加性别字段
PUT /es01/_mapping
{
  "properties":{
     "sex":{
        "type": "long"
      }
  }
}

#删除索引库
delete /es01

2:ES的使用(DSL操作文档-相当于数据)

2.1:什么是文档

文档就是数据,对比mysql的话,就是表中添加数据,但是这里添加的数据是json

2.2:文档的增删改查

对文档增删改查就相当于在mysql表中对于数据的增删改查,便于理解

#添加文档(数据)到索引库(表)  
# PUT /索引库名字/_doc/文档id
PUT /es01/_doc/4
{
  "age":11,
  "email":"12345672@qq.com",
  "info":"小米手机充电器是新鸟传媒公司白嫖的,哦买嘎。好用极了!",
  "name":{
    "firstName":"孙",
    "lastName":"悟空44"
  },
  "sex":2
}
#查询文档(数据)
get /es01/_doc/4

#删除文档(数据)
delete /es01/_doc/1



#修改文档全部字段
PUT /es01/_doc/4
{
  "age":11,
  "email":"12345672@qq.com",
  "info":"小米手机充电器是新鸟传媒公司白嫖的,哦买嘎。好用极了!",
  "name":{
    "firstName":"孙",
    "lastName":"悟空44"
  },
  "sex":2
}

#修改部分字段
PUT /es01/_doc/4
{
  "name":{
    "firstName":"孙",
    "lastName":"悟空444"
  }
}

3:java代码开发

因为前边都是使用kibana的控制台来进行的测试,方便我们理解具体的机制,不是代码。我们在实际的开发过程中是使用代码进行开的,下边介绍Java代码怎么进行开发

首先创建表,添加数据,然后使用Java代码创建索引,对索引进行增删改查,在索引中添加数据,进行增删改查。

3.1:准备工作

1:创建数据表,添加数据,创建springboot项目,生成增删改查代码

DROP TABLE IF EXISTS `tb_hotel`;
CREATE TABLE `tb_hotel`  (
  `id` bigint(20) NOT NULL COMMENT '酒店id',
  `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '酒店名称',
  `address` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '酒店地址',
  `price` int(10) NOT NULL COMMENT '酒店价格',
  `score` int(2) NOT NULL COMMENT '酒店评分',
  `brand` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '酒店品牌',
  `city` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '所在城市',
  `star_name` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '酒店星级,1星到5星,1钻到5钻',
  `business` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '商圈',
  `latitude` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '纬度',
  `longitude` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '经度',
  `pic` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '酒店图片',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Compact;



-- ----------------------------
INSERT INTO `tb_hotel` VALUES (36934, '7天连锁酒店(上海宝山路地铁站店)', '静安交通路40号', 336, 37, '7天酒店', '上海', '二钻', '四川北路商业区', '31.251433', '121.47522', 'https://m.tuniucdn.com/fb2/t1/G1/M00/3E/40/Cii9EVkyLrKIXo1vAAHgrxo_pUcAALcKQLD688AAeDH564_w200_h200_c1_t0.jpg');
INSERT INTO `tb_hotel` VALUES (38609, '速8酒店(上海赤峰路店)', '广灵二路126号', 249, 35, '速8', '上海', '二钻', '四川北路商业区', '31.282444', '121.479385', 'https://m.tuniucdn.com/fb2/t1/G2/M00/DF/96/Cii-TFkx0ImIQZeiAAITil0LM7cAALCYwKXHQ4AAhOi377_w200_h200_c1_t0.jpg');
INSERT INTO `tb_hotel` VALUES (38665, '速8酒店上海中山北路兰田路店', '兰田路38号', 226, 35, '速8', '上海', '二钻', '长风公园地区', '31.244288', '121.422419', 'https://m.tuniucdn.com/fb2/t1/G2/M00/EF/86/Cii-Tlk2mV2IMZ-_AAEucgG3dx4AALaawEjiycAAS6K083_w200_h200_c1_t0.jpg');
INSERT INTO `tb_hotel` VALUES (38812, '7天连锁酒店(上海漕溪路地铁站店)', '徐汇龙华西路315弄58号', 298, 37, '7天酒店', '上海', '二钻', '八万人体育场地区', '31.174377', '121.442875', 'https://m.tuniucdn.com/fb2/t1/G2/M00/E0/0E/Cii-TlkyIr2IEWNoAAHQYv7i5CkAALD-QP2iJwAAdB6245_w200_h200_c1_t0.jpg');
INSERT INTO `tb_hotel` VALUES (39106, '7天连锁酒店(上海莘庄地铁站店)', '闵行莘庄镇七莘路299号', 348, 41, '7天酒店', '上海', '二钻', '莘庄工业区', '31.113812', '121.375869', 'https://m.tuniucdn.com/fb2/t1/G2/M00/D8/11/Cii-T1ku2zGIGR7uAAF1NYY9clwAAKxZAHO8HgAAXVN368_w200_h200_c1_t0.jpg');
INSERT INTO `tb_hotel` VALUES (39141, '7天连锁酒店(上海五角场复旦同济大学店)', '杨浦国权路315号', 349, 38, '7天酒店', '上海', '二钻', '江湾、五角场商业区', '31.290057', '121.508804', 'https://m.tuniucdn.com/fb2/t1/G2/M00/C7/E3/Cii-T1knFXCIJzNYAAFB8-uFNAEAAKYkQPcw1IAAUIL012_w200_h200_c1_t0.jpg');
INSERT INTO `tb_hotel` VALUES (45845, '上海西藏大厦万怡酒店', '虹桥路100号', 589, 45, '万怡', '上海', '四钻', '徐家汇地区', '31.192714', '121.434717', 'https://m.tuniucdn.com/fb3/s1/2n9c/48GNb9GZpJDCejVAcQHYWwYyU8T_w200_h200_c1_t0.jpg');
INSERT INTO `tb_hotel` VALUES (45870, '上海临港豪生大酒店', '新元南路555号', 896, 45, '豪生', '上海', '四星级', '滴水湖临港地区', '30.871729', '121.81959', 'https://m.tuniucdn.com/fb3/s1/2n9c/2F5HoQvBgypoDUE46752ppnQaTqs_w200_h200_c1_t0.jpg');
INSERT INTO `tb_hotel` VALUES (46829, '上海浦西万怡酒店', '恒丰路338号', 726, 46, '万怡', '上海', '四钻', '上海火车站地区', '31.242977', '121.455864', 'https://m.tuniucdn.com/fb3/s1/2n9c/x87VCoyaR8cTuYFZmKHe8VC6Wk1_w200_h200_c1_t0.jpg');
INSERT INTO `tb_hotel` VALUES (47066, '上海浦东东站华美达酒店', '施新路958号', 408, 46, '华美达', '上海', '四钻', '浦东机场核心区', '31.147989', '121.759199', 'https://m.tuniucdn.com/fb3/s1/2n9c/2pNujAVaQbXACzkHp8bQMm6zqwhp_w200_h200_c1_t0.jpg');
INSERT INTO `tb_hotel` VALUES (47478, '速8酒店(上海松江中心店)', '松江荣乐东路677号', 428, 35, '速8', '上海', '二钻', '佘山、松江大学城', '31.016712', '121.261606', 'https://m.tuniucdn.com/filebroker/cdn/res/07/36/073662e1718fccefb7130a9da44ddf5c_w200_h200_c1_t0.jpg');
INSERT INTO `tb_hotel` VALUES (56201, '上海齐鲁万怡大酒店', '东方路838号', 873, 44, '万怡', '上海', '四星级', '浦东陆家嘴金融贸易区', '31.226031', '121.525801', 'https://m.tuniucdn.com/fb2/t1/G6/M00/52/B6/Cii-TF3eXKeIJeN7AASiKHbTtx4AAGRegDSBzMABKJA111_w200_h200_c1_t0.jpg');
INSERT INTO `tb_hotel` VALUES (56214, '上海浦东华美达大酒店', '新金桥路18号', 830, 45, '华美达', '上海', '四星级', '浦东金桥地区', '31.244916', '121.590752', 'https://m.tuniucdn.com/fb3/s1/2n9c/3jtXiuMKZEXJAuKuAkc47yLCjUBt_w200_h200_c1_t0.jpg');
INSERT INTO `tb_hotel` VALUES (56227, '上海圣淘沙万怡酒店', '南桥镇南桥路1号', 899, 45, '万怡', '上海', '四星级', '奉贤开发区', '30.910917', '121.456525', 'https://m.tuniucdn.com/fb2/t1/G6/M00/52/B9/Cii-U13eXSiIdJjXAARSA6FywFYAAGRnwHvy1AABFIb158_w200_h200_c1_t0.jpg');
INSERT INTO `tb_hotel` VALUES (56392, '上海银星皇冠假日酒店', '番禺路400号', 809, 47, '皇冠假日', '上海', '五星级', '徐家汇地区', '31.202768', '121.429524', 'https://m.tuniucdn.com/fb3/s1/2n9c/37ucQ38K3UFdcRqntJ8M5dt884HR_w200_h200_c1_t0.jpg');
INSERT INTO `tb_hotel` VALUES (56852, '上海财大豪生大酒店', '武东路188号', 592, 46, '豪生', '上海', '五钻', '江湾/五角场商业区', '31.304182', '121.492936', 'https://m.tuniucdn.com/fb3/s1/2n9c/2jGHezLZvPZqC9cBGesbP5vAhCXi_w200_h200_c1_t0.jpg');
INSERT INTO `tb_hotel` VALUES (56912, '上海华凯华美达广场酒店', '月华路9号', 747, 40, '华美达', '上海', '四钻', '奉贤开发区', '30.814382', '121.464521', 'https://m.tuniucdn.com/fb3/s1/2n9c/45iaCNCuZavJTxwTLskhVKzwynLD_w200_h200_c1_t0.jpg');
INSERT INTO `tb_hotel` VALUES (56977, '上海五角场华美达大酒店', '黄兴路1888号', 499, 40, '华美达', '上海', '三钻', '江湾/五角场商业区', '31.292932', '121.519759', 'https://m.tuniucdn.com/fb3/s1/2n9c/26VREqAQdaGFvJdAJALVtjxcNMpL_w200_h200_c1_t0.jpg');
INSERT INTO `tb_hotel` VALUES (60214, '上海金茂君悦大酒店', '世纪大道88号(54楼办理入住)', 699, 46, '君悦', '上海', '五星级', '浦东陆家嘴金融贸易区', '31.235152', '121.506082', 'https://m.tuniucdn.com/fb3/s1/2n9c/7Azm3jvGUHuXe3eS1DrixAWVTXY_w200_h200_c1_t0.jpg');
INSERT INTO `tb_hotel` VALUES (60223, '上海希尔顿酒店', '静安华山路250号', 2688, 37, '希尔顿', '上海', '五星级', '静安寺地区', '31.219306', '121.445427', 'https://m.tuniucdn.com/filebroker/cdn/res/92/10/9210e74442aceceaf6e196d61fc3b6b1_w200_h200_c1_t0.jpg');
INSERT INTO `tb_hotel` VALUES (60359, '上海外高桥皇冠假日酒店', '杨高北路1000号', 3299, 46, '皇冠假日', '上海', '五星级', '浦东外高桥地区', '31.338944', '121.590611', 'https://m.tuniucdn.com/fb3/s1/2n9c/VcKUM9zUSiVgDhFioc6mWQoX9ES_w200_h200_c1_t0.jpg');
INSERT INTO `tb_hotel` VALUES (60363, '上海新世界丽笙大酒店', '南京西路88号', 1341, 46, '丽笙', '上海', '五星级', '人民广场地区', '31.23462', '121.47327', 'https://m.tuniucdn.com/fb3/s1/2n9c/2j31b7X3YzGkf4Li3phS6TG1mtwm_w200_h200_c1_t0.jpg');
INSERT INTO `tb_hotel` VALUES (60398, '上海复旦皇冠假日酒店', '邯郸路199号', 924, 47, '皇冠假日', '上海', '五星级', '江湾/五角场商业区', '31.295382', '121.502537', 'https://m.tuniucdn.com/fb3/s1/2n9c/2H1Gk8LHaBWZfYvR6NYYcGTvACmL_w200_h200_c1_t0.jpg');
INSERT INTO `tb_hotel` VALUES (60487, '上海外滩茂悦大酒店', '黄浦路199号', 689, 44, '君悦', '上海', '五星级', '外滩地区', '31.245409', '121.492969', 'https://m.tuniucdn.com/fb3/s1/2n9c/2Swp2h1fdj9zCUKsk63BQvVgKLTo_w200_h200_c1_t0.jpg');
INSERT INTO `tb_hotel` VALUES (60522, '上海嘉豪淮海国际豪生酒店', '汾阳路1号', 425, 45, '豪生', '上海', '四钻', '淮海路/新天地地区', '31.215497', '121.456297', 'https://m.tuniucdn.com/fb3/s1/2n9c/38UBi4QYuaF8jN94CxQ7tb7tjtmZ_w200_h200_c1_t0.jpg');
INSERT INTO `tb_hotel` VALUES (60916, '上海绿地万怡酒店', '沪宜公路3101号', 328, 45, '万怡', '上海', '四钻', '嘉定新城', '31.368523', '121.258567', 'https://m.tuniucdn.com/fb3/s1/2n9c/3VLwG9tTQQnp3M3MTeMTdx9nas9B_w200_h200_c1_t0.jpg');
INSERT INTO `tb_hotel` VALUES (60922, '上海虹桥祥源希尔顿酒店', '红松东路1116号', 1108, 45, '希尔顿', '上海', '五钻', '虹桥地区', '31.18746', '121.395312', 'https://m.tuniucdn.com/fb3/s1/2n9c/tQRqDTFkHnHzMZiDKjcGV81ekvc_w200_h200_c1_t0.jpg');
INSERT INTO `tb_hotel` VALUES (60935, '上海虹口三至喜来登酒店', '四平路59号', 1899, 46, '喜来登', '上海', '五星级', '四川北路商业区', '31.2579', '121.487954', 'https://m.tuniucdn.com/fb3/s1/2n9c/3C3gxLxLjVwnkxJwJm8rd3f38kcd_w200_h200_c1_t0.jpg');
INSERT INTO `tb_hotel` VALUES (61075, '上海雅居乐万豪酒店', '西藏中路555号', 1152, 46, '万豪', '上海', '五钻', '人民广场地区', '31.236681', '121.473529', 'https://m.tuniucdn.com/fb3/s1/2n9c/3FoT16PkXavKsssvktVvVq5Si6Cr_w200_h200_c1_t0.jpg');
INSERT INTO `tb_hotel` VALUES (61083, '上海滴水湖皇冠假日酒店', '自由贸易试验区临港新片区南岛1号', 971, 44, '皇冠假日', '上海', '五钻', '滴水湖临港地区', '30.890867', '121.937241', 'https://m.tuniucdn.com/fb3/s1/2n9c/312e971Rnj9qFyR3pPv4bTtpj1hX_w200_h200_c1_t0.jpg');
INSERT INTO `tb_hotel` VALUES (309208, '北京王府井希尔顿酒店', '王府井东街8号', 1679, 46, '希尔顿', '北京', '五钻', '天安门/王府井地区', '39.914539', '116.413392', 'https://m.tuniucdn.com/fb2/t1/G6/M00/52/10/Cii-TF3ePt2IX9UEAALb6VYBSmoAAGKMgGsuW8AAtwB147_w200_h200_c1_t0.jpg');
INSERT INTO `tb_hotel` VALUES (394559, '北京东方君悦大酒店', '长安街1号东方广场', 686, 45, '君悦', '北京', '五星级', '天安门/王府井地区', '39.909635', '116.414621', 'https://m.tuniucdn.com/fb3/s1/2n9c/3mFqcNSh7eEo9yc3Rw2P5HDNTdDe_w200_h200_c1_t0.jpg');
INSERT INTO `tb_hotel` VALUES (394617, '北京宝辰饭店', '建国门内大街甲18号', 418, 44, '豪生', '北京', '四星级', '北京站/建国门地区', '39.905768', '116.428153', 'https://m.tuniucdn.com/fb3/s1/2n9c/NEYa6EfDHuhhb19Ct85WBbkKHZU_w200_h200_c1_t0.jpg');
INSERT INTO `tb_hotel` VALUES (394796, '北京新云南皇冠假日酒店', '东北三环西坝河太阳宫桥东北角云南大厦', 485, 46, '皇冠假日', '北京', '五星级', '国展中心地区', '39.972409', '116.434698', 'https://m.tuniucdn.com/fb3/s1/2n9c/dfP8K782eTsohQWSRdkd7St9LA2_w200_h200_c1_t0.jpg');
INSERT INTO `tb_hotel` VALUES (395434, '北京希尔顿酒店', '东三环北路东方路1号', 350, 45, '希尔顿', '北京', '五星级', '燕莎/朝阳公园商业区', '39.952703', '116.462387', 'https://m.tuniucdn.com/fb3/s1/2n9c/3fwNbKGhk6XCrkdVyxwhC5uGpLVy_w200_h200_c1_t0.jpg');
INSERT INTO `tb_hotel` VALUES (395702, '北京首都机场希尔顿酒店', '首都机场3号航站楼三经路1号', 222, 46, '希尔顿', '北京', '五钻', '首都机场/新国展地区', '40.048969', '116.619566', 'https://m.tuniucdn.com/fb2/t1/G6/M00/52/10/Cii-U13ePtuIMRSjAAFZ58NGQrMAAGKMgADZ1QAAVn_167_w200_h200_c1_t0.jpg');
INSERT INTO `tb_hotel` VALUES (395787, '北京海航大厦万豪酒店', '霄云路甲26号', 1302, 46, '万豪', '北京', '五钻', '燕莎/朝阳公园商业区', '39.959861', '116.467363', 'https://m.tuniucdn.com/fb3/s1/2n9c/3zFiWi2C9SmbcQwCZgJFQC9ahvs5_w200_h200_c1_t0.jpg');

2:使用kibana的DSL语句创建hotel索引 

put /hotel
{
  "mappings":{
    
    "properties":{
      
      "id":{
        "type": "keyword"
      },
     "name":{
        "type": "text",
        "analyzer":"ik_max_word",
        "copy_to":"all"
      },
      
      "address":{
        "type": "keyword",
        "index": false
      },
      
      "price":{
        "type": "integer"
      },
      "score":{
        "type": "integer"
      },
      
      "brand":{
        "type": "keyword",
        "copy_to":"all"
      },
      "city":{
        "type": "keyword"
      },
      
      "starName":{
        "type": "keyword"
      },
      "business":{
        "type": "keyword",
        "copy_to":"all"
      },
      
      "location":{
        "type": "geo_point"
      },
      
      "pic":{
        "type": "keyword",
        "index": false
      },
      
      "all":{
        "type": "text",
        "analyzer":"ik_max_word"
      }
      
    }
  }
}

#获取索引数据
get /hotel
#删除索引
delete /hotel

3.2:代码操作索引(也就是表的增删改查)

1:导入依赖的jar

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.0.2</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>


         <!-- 8.X版本弃用了的ES的Java REST Client-->
        <dependency>
            <groupId>co.elastic.clients</groupId>
            <artifactId>elasticsearch-java</artifactId>
            <version>8.11.0</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.12.3</version>
        </dependency>

2:配置ElasticsearchClient的bean

@Configuration
public class EsConfig {

    /**
     * 创建ElasticsearchClient的bean
     * @return
     */
    @Bean
    public ElasticsearchClient elasticsearchClient(){
        String serverUrl = "http://172.16.35.136:9200";
        // 创建低级客户端  low-level client
        RestClient restClient = RestClient.builder(HttpHost.create(serverUrl)).build();
        //使用Jackson映射器创建传输
        ElasticsearchTransport transport = new RestClientTransport(restClient, new JacksonJsonpMapper());
        //并创建API客户端
        return new ElasticsearchClient(transport);
    }
}

3:启动项目需要配置SpringBootApplication的exclude属性,否则报错

@MapperScan(value = "com.example.elasticsearch_1.mapper")
//这里需要配置exclude 否则出现jar冲突 报错
@SpringBootApplication(exclude = org.springframework.boot.autoconfigure.elasticsearch.ElasticsearchClientAutoConfiguration.class )
public class ElasticSearch1Application {
    public static void main(String[] args) {
        SpringApplication.run(ElasticSearch1Application.class, args);
    }

}

4:测试代码测试索引的增删改查 

@SpringBootTest
class 索引库操作Demo {

    //并创建API客户端
    ElasticsearchClient esClient = null;

    private static final String hotel_index = "{\n" +
            "  \"mappings\":{\n" +
            "    \n" +
            "    \"properties\":{\n" +
            "      \n" +
            "      \"id\":{\n" +
            "        \"type\": \"keyword\"\n" +
            "      },\n" +
            "      \n" +
            "     \"name\":{\n" +
            "        \"type\": \"text\",\n" +
            "        \"analyzer\":\"ik_max_word\",\n" +
            "        \"copy_to\":\"all\"\n" +
            "      },\n" +
            "      \n" +
            "      \"address\":{\n" +
            "        \"type\": \"keyword\",\n" +
            "        \"index\": false\n" +
            "      },\n" +
            "      \n" +
            "      \n" +
            "      \"price\":{\n" +
            "        \"type\": \"integer\"\n" +
            "      },\n" +
            "      \"score\":{\n" +
            "        \"type\": \"integer\"\n" +
            "      },\n" +
            "      \n" +
            "      \"brand\":{\n" +
            "        \"type\": \"keyword\",\n" +
            "        \"copy_to\":\"all\"\n" +
            "      },\n" +
            "      \"city\":{\n" +
            "        \"type\": \"keyword\"\n" +
            "      },\n" +
            "      \n" +
            "      \"starName\":{\n" +
            "        \"type\": \"keyword\"\n" +
            "      },\n" +
            "      \"business\":{\n" +
            "        \"type\": \"keyword\",\n" +
            "        \"copy_to\":\"all\"\n" +
            "\n" +
            "      },\n" +
            "      \n" +
            "      \"location\":{\n" +
            "        \"type\": \"geo_point\"\n" +
            "      },\n" +
            "      \n" +
            "      \"pic\":{\n" +
            "        \"type\": \"keyword\",\n" +
            "        \"index\": false\n" +
            "      },\n" +
            "      \n" +
            "      \"all\":{\n" +
            "        \"type\": \"text\",\n" +
            "        \"analyzer\":\"ik_max_word\"\n" +
            "      }\n" +
            "      \n" +
            "      \n" +
            "    }\n" +
            "  }\n" +
            "}";

    @BeforeEach
    void es1Test() {
        // URL and API key
        String serverUrl = "http://172.16.35.136:9200";
        String apiKey = "VnVhQ2ZHY0JDZGJrU...";

        // 创建低级客户端  low-level client
        RestClient restClient = RestClient
                .builder(HttpHost.create(serverUrl))
//                .setDefaultHeaders(new Header[]{
//                        new BasicHeader("Authorization", "ApiKey " + apiKey)
//                })
                .build();
        System.out.println(restClient);

        //使用Jackson映射器创建传输
        ElasticsearchTransport transport = new RestClientTransport(restClient, new JacksonJsonpMapper());

        //并创建API客户端
        this.esClient = new ElasticsearchClient(transport);
        System.out.println(esClient);
    }


    //创建索引库
    @Test
    void creatHotelIndex() throws IOException {
        System.out.println(esClient);
        InputStream inputStream = new FileInputStream("/Users/huyiju/work/ideawork2/SpringBootProjects/ElasticSearch_1/src/main/resources/hotel.json");
        CreateIndexResponse createIndexResponse = esClient.indices().create(
                new CreateIndexRequest.Builder()
                        //创建索引
                        .index("hotel")
                        //创建索引内容 外部文件
                        //.withJson(inputStream)
                        //创建索引内容 String字符串的json创建
                        .withJson(new StringReader(hotel_index))
                        .build()
        );
        if (createIndexResponse.acknowledged()) {
            System.out.println("创建hotel索引成功");
        } else {
            System.out.println("创建hotel索引失败");
        }
        System.out.println(createIndexResponse.acknowledged());
    }

    //获取索引库 GetIndexResponse
    @Test
    void getHotelIndex() throws IOException {
        System.out.println(esClient);
        GetIndexResponse getIndexResponse = esClient.indices().get(
                new GetIndexRequest.Builder().index("hotel").build()
        );
        Map<String, IndexState> result = getIndexResponse.result();
        System.out.println(result.get("hotel"));
    }

    //删除索引库 DeleteIndexResponse
    @Test
    void deleteHotelIndex() throws IOException {
        System.out.println(esClient);
        DeleteIndexResponse hotel = esClient.indices().delete(
                new DeleteIndexRequest.Builder().index("hotel")
                        .build()

        );
        System.out.println("删除索引:" + hotel.acknowledged());

    }

    //判断索引库是否存在
    @Test
    void isHotelIndex() throws IOException {
        System.out.println(esClient);
        BooleanResponse hotel = esClient.indices().exists(new ExistsRequest.Builder().index("hotel").build());
        System.out.println("hotel是否存在:" + hotel.value());

    }

    //判断索引库是否存在
    @Test
    void json()  {
        System.out.println("hotel是否存在:" + hotel_index);

    }

}

3.3:代码操作文档(也就是数据的增删改查)

@SpringBootTest
class 文档操作Demo {


    @Autowired
    TbHotelServiceImpl tbHotelService;
    @Autowired
    ElasticsearchClient elasticsearchClient;

    //添加数据
    @Test
    void addDocument() throws IOException {
        //数据库查询到一条数据
        TbHotel hotel = tbHotelService.getById(36934L);
        TbHotelDoc hotelDoc=new TbHotelDoc(hotel);
        System.out.println(hotelDoc);

        //数据插入ES
        IndexRequest indexRequest=new IndexRequest.Builder<TbHotelDoc>()
                .id("11")
                .index("hotel")
                .document(hotelDoc).build();
        elasticsearchClient.index(indexRequest);
    }

    //批量添加数据
    @Test
    void addAllDocument() throws IOException {
        //查询所有数据
        List<TbHotel> list = tbHotelService.list();
        System.out.println("list:"+list.size());
        //将数据添加到ES中
        BulkRequest.Builder builder = new BulkRequest.Builder();

        for (TbHotel hotel : list) {
            TbHotelDoc hotelDoc=new TbHotelDoc(hotel);
            builder.operations(op->op.index(
                    idx->idx.index("hotel")
                            .id(hotelDoc.getId().toString())
                            .document(hotelDoc)
            ));
        }


        elasticsearchClient.bulk(builder.refresh(Refresh.WaitFor).build());

    }

    //根据id查询数据
    @Test
    void selectByIDDocument() throws IOException {
       //GetRequest查询 查询单个
        System.out.println("========查询单个GetRequest=======");
        GetRequest getRequest = new GetRequest.Builder().index("hotel").id("11").build();
        GetResponse<TbHotelDoc> tbHotelDocGetResponse = elasticsearchClient.get(getRequest, TbHotelDoc.class);
        boolean found = tbHotelDocGetResponse.found();
        if (found) {
            TbHotelDoc hotelDoc = tbHotelDocGetResponse.source();
            System.out.println("查询数据是:"+hotelDoc);

        } else {
            System.out.println("没有查询到");
        }

    }

    //查询全部数据
    //默认查询10条
    @Test
    void selectAlLDocument() throws IOException {
        //查询全部SearchRequest
        System.out.println("========查询全部SearchRequest=======");
        SearchRequest searchRequest = new SearchRequest.Builder().index("hotel").build();
        SearchResponse<TbHotelDoc> search = elasticsearchClient.search(searchRequest, TbHotelDoc.class);
        List<Hit<TbHotelDoc>> hits = search.hits().hits();
        for (Hit<TbHotelDoc> hit : hits) {
            TbHotelDoc hotel = hit.source();
            System.out.println(hotel);
        }
    }

    //根据id修改数据
    @Test
    void updateDocument() throws IOException {
        TbHotelDoc tbHotelDoc=new TbHotelDoc();
        //需要更新哪个字段就赋值哪个字段
        tbHotelDoc.setAddress("上海xx");
        //修改这条数据
        UpdateRequest<TbHotelDoc, TbHotelDoc> updateRequest = new UpdateRequest.Builder<TbHotelDoc, TbHotelDoc>()
                .index("hotel")
                .id("11")
                .doc(tbHotelDoc)
                .build();
        UpdateResponse<TbHotelDoc> update = elasticsearchClient.update(updateRequest, TbHotelDoc.class);
        System.out.println(update);

        //直接使用接口编程修改
        TbHotelDoc hotelDoc=new TbHotelDoc();
        //需要更新哪个字段就赋值哪个字段
        hotelDoc.setCity("xx");
        elasticsearchClient.update(updateRequest1->updateRequest1
                        .index("hotel")
                        .id("11")
                        .doc(hotelDoc)
                ,TbHotelDoc.class);

    }


    //根据id删除数据
    @Test
    void deleteDocument() throws IOException {
        DeleteResponse hotel = elasticsearchClient.delete(deleteRequest -> deleteRequest
                .index("hotel")
                .id("12"));
        System.out.println(hotel);
        //删除全部
//        elasticsearchClient.delete(deleteRequest->deleteRequest
//                .index("hotel").id("11"));

    }


}

4:DSL实现复杂的查询

在上边我们只认识的对索引的创建,数据库查询数据之后,将数据插入ES,根据ID进行增删改查查,但是实际的开发过程中,因为有很多字段,不可能只对ID进行操作,需要对字段进行查询,这就有了DSL的复杂查询,类似于mysql的各种字段查询

4.1:DSL对单个字段的查询

#--------全文检索  针对type=text类型-------
#根据type=text字段进行分词,然后查询,只能有一个条件
#match 单个匹配
get /hotel/_search
{
  "query":{
    "match": {
      "all": "外滩如家"
    }
  }
}

#根据type=text字段进行分词,然后查询,可以有多个条件
#multi_match 多重匹配 参与字段越多 性能越低,
#建议利用"copy_to":"all" 将多个字段合并为一个字段  类似于mysql的联合索引
get /hotel/_search
{
  "query":{
    "multi_match": {
      "query": "外滩如家",
      "fields": ["name","brand","business"]
    }
  }
}

#--------精确  针对type=keyword、id、数值、布尔类型 这些字段必须精确匹配------
#term 精确匹配
# city "type": "keyword" 的精确查询
# select * from tb_hotel where city="上海"

get /hotel/_search
{
  "query":{
    "term": {
      "city": {
        "value": "上海"
      }
    }
  }
}

# score "type": "integer" 的精确查询
# select * from tb_hotel where score=35

get /hotel/_search
{
  "query":{
    "term": {
      "score": {
        "value": "35"
      }
    }
  }
}


# score "type": "integer" 的精确查询
# select * from tb_hotel where star_name="四星级"
get /hotel/_search
{
  "query":{
    "term": {
      "starName": {
        "value": "四星级"
      }
    }
  }
}

#range 查询price价格的区间 
#相当于 select * from tb_hotel where price>=1100 and price<=1200
get /hotel/_search
{
  "query":{
    "range": {
      "price": {
        "gte": 1100,
        "lte": 1200
      }
    }
  }
}

#经纬度查询 查询指定举例的所有数据
#longitude、latitude 经度、纬度
#查询经纬度是31.21,121.5范围15KM的所有数据
#distance 以指定位置为中心的圆的半径。落入这个圆圈的点被认为是匹配的。距离可以用各种单位来表示
get /hotel/_search
{
  "query":{
    "geo_distance": {
      "distance": "2km",
      "location": {
        "lat": 31.21,
        "lon": 121.5
      }
    }
  }
}

4.2:DSL对多个字段的查询

#---------------复合查询
#must 相当于sql的与 (city="上海" and price<=200) 
#should 相当于sql的或
#must_not 相当于不等于 不参与算分
#filter 也是必须匹配 不参与算分
#select * from tb_hotel where  city="上海" and price<=210
get /hotel/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "term": {
            "city": {
              "value": "上海"
            }
          }
        },
        {
          "range": {
            "price": {
              "lte": 210
            }
          }
        }
      ],
      "should": [
        {
          "term": {
            "brand": {
              "value": "如家"
            }
          }
        }
      ]
    }
  }
}

#select * from tb_hotel where  name like "%如家%" and price<=400  查询到27条数据
#并且距离指定位置 10km以内 只有三家
#_score分数不一致
get /hotel/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "name": "如家"
          }
        }
      ],
      "must_not": [
        {
          "range": {
            "price": {
              "gt": 400
            }
          }
        }
      ],
      "filter": [
        {
          "geo_distance": {
            "distance": "10km",
            "location": {
              "lat": 31.21,
              "lon": 121.5
            }
          }
        }
      ]
    }
  }
}


#select * from tb_hotel where  name like "%如家%" and price<=400  查询到27条数据
#并且距离指定位置 10km以内 只有三家
#影响算分 _score分数不一致

get /hotel/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "name": "如家"
          }
        },
        {
          "geo_distance": {
            "distance": "10km",
            "location": {
              "lat": 31.21,
              "lon": 121.5
            }
          }
        }
        
      ],
      "must_not": [
        {
          "range": {
            "price": {
              "gt": 400
            }
          }
        }
      ]
    }
  }
}


#---------------------------排序------
#select * from tb_hotel where  name like "%如家%" and price<=400  查询到27条数据
#并且距离指定位置 10km以内 只有三家
#_score分数不一致

get /hotel/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "name": "如家"
          }
        },
        {
          "geo_distance": {
            "distance": "10km",
            "location": {
              "lat": 31.21,
              "lon": 121.5
            }
          }
        }
        
      ],
      "must_not": [
        {
          "range": {
            "price": {
              "gt": 400
            }
          }
        }
      ]
    }
  },
  "sort": [
    {
      "price":"asc"
    },
    {
      "score":"desc"
    }
  ]
}

#对location的位置进行排序 举例坐标点距离位置开始排序
get /hotel/_search
{
  "query": {
    "match_all": {}
  },
  "sort": [
    {
      "_geo_distance": {
        "location": {
          "lat": 31.034661,
          "lon": 121.612282
        },
        "order":"asc",
        "unit":"km"
      }
    }
  ]
}

#分页 select * from table limit start,size;
#from 相当于limit的start 起始位置 默认值是0
#size 相当于limit的size 查询数据长度
#from+size<=10000 因为分页是结果分页  查询全部 在分页

get /hotel/_search
{
  "query": {
    "match_all": {}
  },
  "from":99,
  "size":10,
  "sort": [
    {
      "_geo_distance": {
        "location": {
          "lat": 31.034661,
          "lon": 121.612282
        },
        "order":"asc",
        "unit":"km"
      }
    }
  ]
}


#高亮实现
#highlight 设置高亮字段
#<em>如家</em>酒店(北京良乡西路店) 
#name字段的返回值有了<em>标签 前端只需要设置css就行了
get /hotel/_search
{
  "query": {
    "match": {
      "all": "如家"
    }
  },
  "highlight": {
    "fields": {
      "name":{
        "require_field_match": "false"
      }
    }
  }
}



#高亮实现
get /hotel/_search
{
  "query": {
    "match": {
      "name": "如家"
    }
  },
  "highlight": {
        "boundary_scanner_locale":"zh_CN",
        "fields": {
            "name": {
                "pre_tags": [
                    "<em>"
                ],
                "post_tags": [
                    "</em>"
                ]
            }
        }
    }

}

5:java代码复杂查询

5.1:Java代码简单查询

相当于sql的根据ID的增删改查,批量添加数据库

@SpringBootTest
class 文档操作_简单查询Demo {


    @Autowired
    TbHotelServiceImpl tbHotelService;
    @Autowired
    ElasticsearchClient elasticsearchClient;

    //添加数据 IndexRequest
    @Test
    void addDocument() throws IOException {
        //数据库查询到一条数据
        TbHotel hotel = tbHotelService.getById(36934L);
        TbHotelDoc hotelDoc=new TbHotelDoc(hotel);
        System.out.println(hotelDoc);

        //数据插入ES
        IndexRequest indexRequest=new IndexRequest.Builder<TbHotelDoc>()
                .id("11")
                .index("hotel")
                .document(hotelDoc).build();
        elasticsearchClient.index(indexRequest);
    }

    //批量添加数据 BulkRequest
    @Test
    void addAllDocument() throws IOException {
        //查询所有数据
        List<TbHotel> list = tbHotelService.list();
        System.out.println("list:"+list.size());
        //将数据添加到ES中
        BulkRequest.Builder builder = new BulkRequest.Builder();

        for (TbHotel hotel : list) {
            TbHotelDoc hotelDoc=new TbHotelDoc(hotel);
            builder.operations(op->op.index(
                    idx->idx.index("hotel")
                            .id(hotelDoc.getId().toString())
                            .document(hotelDoc)
            ));
        }


        elasticsearchClient.bulk(builder.refresh(Refresh.WaitFor).build());

    }

    //根据id查询数据 GetRequest
    @Test
    void selectByIDDocument() throws IOException {
       //GetRequest查询 查询单个
        System.out.println("========查询单个GetRequest=======");
        GetRequest getRequest = new GetRequest.Builder().index("hotel").id("36934").build();
        GetResponse<TbHotelDoc> tbHotelDocGetResponse = elasticsearchClient.get(getRequest, TbHotelDoc.class);
        boolean found = tbHotelDocGetResponse.found();
        if (found) {
            TbHotelDoc hotelDoc = tbHotelDocGetResponse.source();
            System.out.println("查询数据是:"+hotelDoc);

        } else {
            System.out.println("没有查询到");
        }

    }

    //查询全部数据 SearchRequest
    //默认查询10条
    @Test
    void selectAlLDocument() throws IOException {
        //查询全部SearchRequest
        System.out.println("========查询全部SearchRequest=======");
        SearchRequest searchRequest = new SearchRequest.Builder().index("hotel").build();
        SearchResponse<TbHotelDoc> search = elasticsearchClient.search(searchRequest, TbHotelDoc.class);
        List<Hit<TbHotelDoc>> hits = search.hits().hits();
        for (Hit<TbHotelDoc> hit : hits) {
            TbHotelDoc hotel = hit.source();
            System.out.println(hotel);
        }
    }

    //根据id修改数据 UpdateRequest
    @Test
    void updateDocument() throws IOException {
        TbHotelDoc tbHotelDoc=new TbHotelDoc();
        //需要更新哪个字段就赋值哪个字段
        tbHotelDoc.setAddress("上海xx");
        //修改这条数据
        UpdateRequest<TbHotelDoc, TbHotelDoc> updateRequest = new UpdateRequest.Builder<TbHotelDoc, TbHotelDoc>()
                .index("hotel")
                .id("36934")
                .doc(tbHotelDoc)
                .build();
        UpdateResponse<TbHotelDoc> update = elasticsearchClient.update(updateRequest, TbHotelDoc.class);
        System.out.println(update);

        //直接使用接口编程修改
        TbHotelDoc hotelDoc=new TbHotelDoc();
        //需要更新哪个字段就赋值哪个字段
        hotelDoc.setCity("xx");
        elasticsearchClient.update(updateRequest1->updateRequest1
                        .index("hotel")
                        .id("36934")
                        .doc(hotelDoc)
                ,TbHotelDoc.class);

    }


    //根据id删除数据 deleteRequest
    @Test
    void deleteDocument() throws IOException {
        DeleteResponse hotel = elasticsearchClient.delete(deleteRequest -> deleteRequest
                .index("hotel")
                .id("12"));
        System.out.println(hotel);
        //删除全部
//        elasticsearchClient.delete(deleteRequest->deleteRequest
//                .index("hotel").id("11"));

    }


}

5.2:Java代码复杂查询

相当于的sql的where 后边跟随多个条件

@SpringBootTest
class 文档操作_复杂查询Demo {


    @Autowired
    TbHotelServiceImpl tbHotelService;
    @Autowired
    ElasticsearchClient elasticsearchClient;

    //查询全部数据 默认分页  查询10条数据
    // select * from tb_hotel limit 0,10
    @Test
    void selectAll() throws IOException {
        SearchRequest searchRequest = new SearchRequest.Builder()
                .index("hotel")
                .build();
        SearchResponse<TbHotelDoc> search = elasticsearchClient.search(searchRequest, TbHotelDoc.class);
        long value = search.hits().total().value();
        System.out.println(value);
        List<Hit<TbHotelDoc>> hits = search.hits().hits();
        for (int i = 0; i < hits.size(); i++) {
            System.out.println("数据是" + i + ":" + hits.get(i).source());

        }

        System.out.println("=====分割线======");
        SearchResponse<TbHotelDoc> search1 = elasticsearchClient.search(s ->
                        s.index("hotel")
                                .query(q ->
                                        q.matchAll(QueryBuilders.matchAll().build()))
                , TbHotelDoc.class
        );
        List<Hit<TbHotelDoc>> hits1 = search1.hits().hits();
        for (int i = 0; i < hits1.size(); i++) {
            System.out.println("数据是" + i + ":" + hits1.get(i).source());
        }
    }


    //查询全部数据
    //match 查询字段必须是text 只能有一个条件
    @Test
    void matchTest() throws IOException {
        System.out.println("=====match测试======");

        SearchResponse<TbHotelDoc> search1 = elasticsearchClient.search(s ->
                        s.index("hotel")
                                .query(q ->
                                        q.match(t -> t.query("如家").field("all")))
                , TbHotelDoc.class
        );

        long value = search1.hits().total().value();
        System.out.println("查询行数:" + value);
        List<Hit<TbHotelDoc>> hits1 = search1.hits().hits();
        for (int i = 0; i < hits1.size(); i++) {
            System.out.println("数据是" + i + ":" + hits1.get(i).source());
        }
    }

    //精准匹配
    //#--------精确  针对type=keyword、id、数值、布尔类型 这些字段必须精确匹配------
    //            #term 精确匹配
    //# city "type": "keyword" 的精确查询
    //select * from tb_hotel where city="上海"
    //select * from tb_hotel where score=35
    //select * from tb_hotel where starName="四星级"

    @Test
    void term1Test() throws IOException {
        System.out.println("=====term测试======");
        SearchResponse<TbHotelDoc> search1 = elasticsearchClient.search(
                s -> s.index("hotel")
                        .query(q ->
                                //q.term(t->t.field("city").value("上海"))
                                //q.term(t->t.field("score").value(35))
                                q.term(t -> t.field("starName").value("四星级"))
                        )
                , TbHotelDoc.class
        );
        long value = search1.hits().total().value();
        System.out.println("查询行数:" + value);
        List<Hit<TbHotelDoc>> hits1 = search1.hits().hits();
        for (int i = 0; i < hits1.size(); i++) {
            System.out.println("数据是" + i + ":" + hits1.get(i).source());
        }
    }


    /**
     * #---------------复合查询
     * #must 相当于sql的与 (city="上海" and price<=200)
     * #should 相当于sql的或
     * #must_not 相当于不等于 不参与算分
     * #filter 也是必须匹配 不参与算分
     * select * from tb_hotel where  city="上海" and price<=200 and price>=100 and brand="如家" limit 0,5 order by price desc
     */
    @Test
    void boolTest() throws IOException {
        System.out.println("=====复合查询测试======");
//        BoolQuery boolQuery = QueryBuilders.bool().build();

        Query city = MatchQuery.of(o -> o.field("city").query("上海"))._toQuery();
        Query price = RangeQuery.of(o -> o.field("price").gt(JsonData.of(100)).lt(JsonData.of(200)))._toQuery();
        Query filter = MatchQuery.of(o -> o.field("brand").query("如家"))._toQuery();
        Query filter1 = MatchQuery.of(o -> o.field("starName").query("二钻"))._toQuery();

//
//        boolQuery.must().add(city);
//        boolQuery.must().add(price);
//        boolQuery.filter().add(filter);


        SearchResponse<TbHotelDoc> search1 = elasticsearchClient.search(
                s -> s.index("hotel")
                        .query(q -> q.bool(builder -> builder
                                        .must(city)
                                        .must(price)
                                        .filter(filter)
                                        .filter(filter1)


                                )
                        )
                        .sort(ss -> ss.field(f -> f.field("price").order(SortOrder.Desc)))
                        .from(0)//数据起始位置 用于分页
                        .size(5)//数据长度  用于分页
                        .highlight(h -> h.fields("name", f -> f
                                        .preTags("<em>")
                                        .postTags("</em>")
                                ).requireFieldMatch(false)
                        )
                , TbHotelDoc.class
        );
        long value = search1.hits().total().value();
        System.out.println("查询行数:" + value);
        List<Hit<TbHotelDoc>> hits1 = search1.hits().hits();
        for (int i = 0; i < hits1.size(); i++) {
            TbHotelDoc source = hits1.get(i).source();
            String name = hits1.get(i).highlight().get("name").get(0);
            source.setName(name);
            System.out.println("数据是" + i + ":" + source);

        }
    }


}

复杂查询2案例:

模拟实际的应用程序,前端点击品牌、价格、城市、星级、地理坐标等按钮选择酒店,这里就是ES的代码实现方式

  @Autowired
    ElasticsearchClient elasticsearchClient;

    /**
     * 前端controller接受json 转换成参数实体
     * {
     *     "key":"",
     *     "page":1,
     *     "size":10,
     *     "sortBy":"price",
     *     "city":"上海",
     *     "brand":"万豪",
     *     "starName": "",
     *     "minPrice": 0,
     *     "maxPrice":1000,
     *     "locaction":"31.119187,121.618966"
     * }
     *
     * RequestParams属性如下
     *      String key;//搜索关键字
     *      Integer page;//当前页
     *      Integer size;//当前页 数据长度
     *      String sortBy;//排序字段
     *      String city;//城市
     *      String brand;//品牌
     *      String starName;//星级
     *      Integer minPrice;//最小价格
     *      Integer maxPrice;//最大价格
     *      String location;//位置坐标
     *      
     * <p>
     * ES查询数据
     * select * from tb_hotel where  city="上海" and price<=200 and price>=100 and brand="如家"
     */
    @Override
    public PageResult getAllHotel(RequestParams requestParams) {

        //构建BoolQuery
        BoolQuery.Builder boolQuery = QueryBuilders.bool();
        //判断关键字是否为空
        String key = requestParams.getKey();//key是关键字
        Query keys;
        if (key == null || ("").equals(key)) {
            keys = QueryBuilders.matchAll().build()._toQuery();
            boolQuery.must(keys);
        } else {
            keys = MatchQuery.of(o -> o.field("all").query(key))._toQuery();
            boolQuery.must(keys);
        }


        //1:判断city是否为空
        String city = requestParams.getCity();
        Query filter_city = null;
        if (city != null && !city.equals("")) {
            filter_city = MatchQuery.of(o -> o.field("city").query(city))._toQuery();
            boolQuery.filter(filter_city);
        }


        //2:判断brand 品牌 是否为空
        String brand = requestParams.getBrand();
        Query filter_brand = null;
        if (brand != null && !brand.equals("")) {
            filter_brand = MatchQuery.of(o -> o.field("brand").query(brand))._toQuery();
            boolQuery.filter(filter_brand);
        }


        //3:判断starName 星级 是否为空
        String starName = requestParams.getStarName();
        Query filter_starName = null;
        if (starName != null && !starName.equals("")) {
            filter_starName = MatchQuery.of(o -> o.field("starName").query(starName))._toQuery();
            boolQuery.filter(filter_starName);
        }

        //4:判断Price 价格 是否为空
        Integer minPrice = requestParams.getMinPrice();
        Integer maxPrice = requestParams.getMaxPrice();

        Query filter_Price;
        if (minPrice != null && !maxPrice.equals("")) {
            filter_Price = RangeQuery.of(o -> o.field("price").gt(JsonData.of(minPrice)).lt(JsonData.of(maxPrice)))._toQuery();
            boolQuery.filter(filter_Price);
        }
        //5:判断locaction 坐标 是否为空 按照距离排序
        // "lat":31.034661,
        //  "lon":121.612282
        String location = requestParams.getLocaction();
        GeoLocation of = null;
        if (location != null && !location.equals("")) {
            String[] split = location.split(",");
            //这是地理坐标
            of = GeoLocation.of(g -> g.latlon(l -> l.lat(Double.parseDouble(split[0])).lon(Double.parseDouble(split[1]))));
        }


        BoolQuery build = boolQuery.build();
        //分页参数
        Integer page = requestParams.getPage();
        Integer size = requestParams.getSize();
        //ES查询数据
        SearchResponse<TbHotelDoc> search1 = null;
        try {


            GeoLocation finalOf = of;
            search1 = elasticsearchClient.search(
                    s -> s.index("hotel")
                            .query(builder -> builder.bool(build)
                            )
                            //.sort(ss -> ss.field(f -> f.field("price").order(SortOrder.Desc)))
                            .sort(ss -> ss.geoDistance(g -> g
                                    .field("location")
                                    .location(finalOf)
                                    .order(SortOrder.Asc)
                                    .unit(DistanceUnit.Kilometers)))

                            .from((page - 1) * size)//数据起始位置 用于分页
                            .size(size)//数据长度  用于分页
                    , TbHotelDoc.class
            );
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }

        //封装返回值数据
        long total = search1.hits().total().value();
        List<TbHotelDoc> list = new ArrayList<>();

        List<Hit<TbHotelDoc>> hits1 = search1.hits().hits();
        for (int i = 0; i < hits1.size(); i++) {
            //获取查询距离 b的值就是查询数据 到指定地点的的距离
            List<FieldValue> sort = hits1.get(i).sort();
            double b = sort.get(0).doubleValue();
            //获取查询酒店结果 用自定义的TbHotelDoc封装
            TbHotelDoc source = hits1.get(i).source();
            //将距离数据set进去
            source.setJuli(b);
            list.add(source);
            System.out.println("数据是" + i + ":" + source);
        }
        //返回结果PageResult 两个参数
        //Long total; es的数据总行数
        //List<TbHotelDoc> tbHotelDocs; 返回结果集
        PageResult pageResult = new PageResult();
        pageResult.setTotal(total);
        pageResult.setTbHotelDocs(list);

        return pageResult;
    }

  • 21
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值