批量操作-脚本
- #批量操作
- #1.删除5号
- #新增8号
- #更新2号 name为2号
- POST _bulk
- {"delete":{"_index":"person1","_id":"5"}}
- {"create":{"_index":"person1","_id":"8"}}
- {"name":"八号","age":18,"address":"北京"}
- {"update":{"_index":"person1","_id":"2"}}
- {"doc":{"name":"2号"}}
批量操作-java
- /**
- * Bulk 批量操作
- */
- @Test
- public void test2() throws IOException {
- //创建bulkrequest对象,整合所有操作
- BulkRequest bulkRequest =new BulkRequest();
- /*
- # 1. 删除5号记录
- # 2. 添加6号记录
- # 3. 修改3号记录 名称为 “三号”
- */
- //添加对应操作
- //1. 删除5号记录
- DeleteRequest deleteRequest=new DeleteRequest("person1","5");
- bulkRequest.add(deleteRequest);
- //2. 添加6号记录
- Map
map=new HashMap<>(); - map.put("name","六号");
- IndexRequest indexRequest=new IndexRequest("person1").id("6").source(map);
- bulkRequest.add(indexRequest);
- //3. 修改3号记录 名称为 “三号”
- Map
mapUpdate=new HashMap<>(); - mapUpdate.put("name","三号");
- UpdateRequest updateRequest=new UpdateRequest("person1","3").doc(mapUpdate);
- bulkRequest.add(updateRequest);
- //执行批量操作
- BulkResponse response = client.bulk(bulkRequest,
- RequestOptions.DEFAULT);
- System.out.println(response.status());
- }
- PUT goods
- {
- "mappings": {
- "properties": {
- "title": {
- "type": "text",
- "analyzer": "ik_smart"
- },
- "price": {
- "type": "double"
- },
- "createTime": {
- "type": "date"
- },
- "categoryName": {
- "type": "keyword"
- },
- "brandName": {
- "type": "keyword"
- },
- "spec": {
- "type": "object"
- },
- "saleNum": {
- "type": "integer"
- },
- "stock": {
- "type": "integer"
- }
- }
- }
- }
第二步:java代码进行数据导入
- /**
- * 从Mysql 批量导入 elasticSearch
- */
- @Test
- public void test3() throws IOException {
- //1.查询所有数据,mysql
- List
goodsList = goodsMapper.findAll(); - //2.bulk导入
- BulkRequest bulkRequest=new BulkRequest();
- //2.1 循环goodsList,创建IndexRequest添加数据
- for (Goods goods : goodsList) {
- //2.2 设置spec规格信息 Map的数据 specStr:{}
- String specStr = goods.getSpecStr();
- //将json格式字符串转为Map集合
- Map map = JSON.parseObject(specStr, Map.class);
- //设置spec map
- goods.setSpec(map);
- //将goods对象转换为json字符串
- String data = JSON.toJSONString(goods);
- IndexRequest indexRequest=new
- IndexRequest("goods").source(data,XContentType.JSON);
- bulkRequest.add(indexRequest);
- }
- BulkResponse response = client.bulk(bulkRequest,
- RequestOptions.DEFAULT);
- System.out.println(response.status());
- }
脚本
- # 默认情况下,es一次展示10条数据,通过from和size来控制分页
- # 查询结果详解
- GET goods/_search
- {
- "query": {
- "match_all": {}
- },
- "from": 0,
- "size": 100
- }
- GET g
java
- /**
- * 查询所有
- * 1. matchAll
- * 2. 将查询结果封装为Goods对象,装载到List中
- * 3. 分页。默认显示10条
- */
- @Test
- public void matchAll() throws IOException {
- //2. 构建查询请求对象,指定查询的索引名称
- SearchRequest searchRequest=new SearchRequest("goods");
- //4. 创建查询条件构建器SearchSourceBuilder
- SearchSourceBuilder sourceBuilder=new SearchSourceBuilder();
- //6. 查询条件
- QueryBuilder queryBuilder= QueryBuilders.matchAllQuery();
- //5. 指定查询条件
- sourceBuilder.query(queryBuilder);
- //3. 添加查询条件构建器 SearchSourceBuilder
- searchRequest.source(sourceBuilder);
- // 8 . 添加分页信息 不设置 默认10条
- // sourceBuilder.from(0);
- // sourceBuilder.size(100);
- //1. 查询,获取查询结果
- SearchResponse searchResponse = client.search(searchRequest,
- RequestOptions.DEFAULT);
- //7. 获取命中对象 SearchHits
- SearchHits hits = searchResponse.getHits();
- //7.1 获取总记录数
- Long total= hits.getTotalHits().value;
- System.out.println("总数:"+total);
- //7.2 获取Hits数据 数组
- SearchHit[] hits1 = hits.getHits();
- //获取json字符串格式的数据
- List
goodsList = new ArrayList<>(); - for (SearchHit searchHit : hits1) {
- String sourceAsString = searchHit.getSourceAsString();
- //转为java对象
- Goods goods = JSON.parseObject(sourceAsString, Goods.class);
- goodsList.add(goods);
- }
- for (Goods goods : goodsList) {
- System.out.println(goods);
- }
- }
text :会分词,不支持聚合keyword :不会分词,将全部内容作为一个词条,支持聚合
termQuery和matchQuery作用类似,但是是用在查询条件上的,分别代表的不同的查询方式,termQuery不会对查询条件进行分词,matchQuery则会对查询条件进行分词
- GET goods/_search
- {
- "query": {
- "term": {
- "title": {
- "value": "华为手机"
- }
- }
- }
- }
- # match查询
- GET goods/_search
- {
- "query": {
- "match": {
- "title": "华为手机"
- }
- },
- "size": 500
- }
term query 会去倒排索引中寻找确切的 term ,它并不知道分词器的存在。这种查询适合 keyword 、numeric 、 date类型match query 知道分词器的存在。并且理解是如何被分词的
"* 华 *" 包含华字的" 华 *" 华字后边多个字符" 华 ?" 华字后边多个字符"* 华 " 或 "? 华 " 会引发全表(全索引)扫描 注意效率问题
- # wildcard 查询。查询条件分词,模糊查询
- GET goods/_search
- {
- "query": {
- "wildcard": {
- "title": {
- "value": "华*"
- }
- }
- }
- }
\W :匹配包括下划线的任何单词字符,等价于 [A-Z a-z 0-9_] 开头的反斜杠是转义符+ 号多次出现(.)* 为任意字符正则查询取决于正则表达式的效率
- GET goods/_search
- {
- "query": {
- "regexp": {
- "title": "\\w+(.)*"
- }
- }
- }
- GET goods/_search
- {
- "query": {
- "prefix": {
- "brandName": {
- "value": "三"
- }
- }
- }
- }
- //模糊查询
- WildcardQueryBuilder query = QueryBuilders.wildcardQuery("title", "华*");//华后多
- 个字符
- //正则查询
- RegexpQueryBuilder query = QueryBuilders.regexpQuery("title", "\\w+(.)*");
- //前缀查询
- PrefixQueryBuilder query = QueryBuilders.prefixQuery("brandName", "三");
- # 范围查询
- GET goods/_search
- {
- "query": {
- "range": {
- "price": {
- "gte": 2000,
- "lte": 3000
- }
- }
- },
- "sort": [
- {
- "price": {
- "order": "desc"
- }
- }
- ]
-
- }
- # queryString
- GET goods/_search
- {
- "query": {
- "query_string": {
- "fields": ["title","categoryName","brandName"],
- "query": "华为 AND 手机"
- }
- }
- }
- GET goods/_search
- {
- "query": {
- "simple_query_string": {
- "fields": ["title","categoryName","brandName"],
- "query": "华为 AND 手机"
- }
- }
- }
- GET goods/_search
- {
- "query": {
- "query_string": {
- "fields": ["title","brandName","categoryName"],
- "query": "华为手机 "
- , "default_operator": "AND"
- }
- }
- }
- QueryStringQueryBuilder query = QueryBuilders.queryStringQuery("华为手
- 机").field("title").field("categoryName")
- .field("brandName").defaultOperator(Operator.AND);
- GET goods/_search
- {
- "query": {
- "simple_query_string": {
- "fields": ["title","brandName","categoryName"],
- "query": "华为手机 "
- , "default_operator": "OR"
- }
- }
- }
- # boolquery
- #must和filter配合使用时,max_score(得分)是显示的
- #must 默认数组形式
- GET goods/_search
- {
- "query": {
- "bool": {
- "must": [
- {
- "term": {
- "brandName": {
- "value": "华为"
- }
- }
- }
- ],
- "filter": [
- {
- "term": {
- "title": "手机"
- }
- },
- {
- "range": {
- "price": {
- "gte": 2000,
- "lte": 3000
- }
- }
- }
- ]
- }
- }
- }
- #filter 单独使用 filter可以是单个条件,也可多个条件(数组形式)
- {
- "query": {
- "bool": {
- "filter": [
- {
- "term": {
- "brandName": {
- "value": "华为"
- }
- }
- }
- ]
- }
- }
- }
- //1.构建boolQuery
- BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
- //2.构建各个查询条件
- //2.1 查询品牌名称为:华为
- TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("brandName","华为");
- boolQuery.must(termQueryBuilder);
- //2.2. 查询标题包含:手机
- MatchQueryBuilder matchQuery = QueryBuilders.matchQuery("title", "手机");
- boolQuery.filter(matchQuery);
- //2.3 查询价格在:2000-3000
- RangeQueryBuilder rangeQuery = QueryBuilders.rangeQuery("price");
- rangeQuery.gte(2000);
- rangeQuery.lte(3000);
- boolQuery.filter(rangeQuery);
- sourceBuilder.query(boolQuery);
- # 聚合查询
- # 指标聚合 聚合函数
- GET goods/_search
- {
- "query": {
- "match": {
- "title": "手机"
- }
- },
- "aggs": {
- "max_price": {
- "max": {
- "field": "price"
- }
- }
- }
- }
- # 桶聚合 分组
- GET goods/_search
- {
- "query": {
- "match": {
- "title": "手机"
- }
- },
- "aggs": {
- "goods_brands": {
- "terms": {
- "field": "brandName",
- "size": 100
- }
- }
- }
- }
- /**
- * 聚合查询:桶聚合,分组查询
- * 1. 查询title包含手机的数据
- * 2. 查询品牌列表
- */
- @Test
- public void testAggQuery() throws IOException {
- SearchRequest searchRequest=new SearchRequest("goods");
- SearchSourceBuilder sourceBuilder=new SearchSourceBuilder();
- //1. 查询title包含手机的数据
- MatchQueryBuilder queryBuilder = QueryBuilders.matchQuery("title", "手机");
- sourceBuilder.query(queryBuilder);
- //2. 查询品牌列表 只展示前100条
- AggregationBuilder
- aggregation=AggregationBuilders.terms("goods_brands").field("brandName").size(100);
- sourceBuilder.aggregation(aggregation);
- searchRequest.source(sourceBuilder);
- SearchResponse searchResponse = client.search(searchRequest,RequestOptions.DEFAULT);
- //7. 获取命中对象 SearchHits
- SearchHits hits = searchResponse.getHits();
- //7.1 获取总记录数
- Long total= hits.getTotalHits().value;
- System.out.println("总数:"+total);
- // aggregations 对象
- Aggregations aggregations = searchResponse.getAggregations();
- //将aggregations 转化为map
- Map
aggregationMap = aggregations.asMap(); - //通过key获取goods_brands 对象 使用Aggregation的子类接收 buckets属性在Terms接口中体现
- // Aggregation goods_brands1 = aggregationMap.get("goods_brands");
- Terms goods_brands =(Terms) aggregationMap.get("goods_brands");
- //获取buckets 数组集合
- List extends Terms.Bucket> buckets = goods_brands.getBuckets();
- Map
map=new HashMap<>(); - //遍历buckets key 属性名,doc_count 统计聚合数
- for (Terms.Bucket bucket : buckets) {
- System.out.println(bucket.getKey());
- map.put(bucket.getKeyAsString(),bucket.getDocCount());
- }
- System.out.println(map);
- }
手机
- GET goods/_search
- {
- "query": {
- "match": {
- "title": "电视"
- }
- },
- "highlight": {
- "fields": {
- "title": {
- "pre_tags": "",
- "post_tags": ""
- }
- }
- }
- /**
- *
- * 高亮查询:
- * 1. 设置高亮
- * * 高亮字段
- * * 前缀
- * * 后缀
- * 2. 将高亮了的字段数据,替换原有数据
- */
- @Test
- public void testHighLightQuery() throws IOException {
- SearchRequest searchRequest = new SearchRequest("goods");
- SearchSourceBuilder sourceBulider = new SearchSourceBuilder();
- // 1. 查询title包含手机的数据
- MatchQueryBuilder query = QueryBuilders.matchQuery("title", "手机");
- sourceBulider.query(query);
- //设置高亮
- HighlightBuilder highlighter = new HighlightBuilder();
- //设置三要素
- highlighter.field("title");
- //设置前后缀标签
- highlighter.preTags("");
- highlighter.postTags("");
- //加载已经设置好的高亮配置
- sourceBulider.highlighter(highlighter);
- searchRequest.source(sourceBulider);
- SearchResponse searchResponse = client.search(searchRequest,
- RequestOptions.DEFAULT);
- SearchHits searchHits = searchResponse.getHits();
- //获取记录数
- long value = searchHits.getTotalHits().value;
- System.out.println("总记录数:"+value);
- List
goodsList = new ArrayList<>(); - SearchHit[] hits = searchHits.getHits();
- for (SearchHit hit : hits) {
- String sourceAsString = hit.getSourceAsString();
- //转为java
- Goods goods = JSON.parseObject(sourceAsString, Goods.class);
- // 获取高亮结果,替换goods中的title
- Map
highlightFields = hit.getHighlightFields(); - HighlightField HighlightField = highlightFields.get("title");
- Text[] fragments = HighlightField.fragments();
- //highlight title替换 替换goods中的title
- goods.setTitle(fragments[0].toString());
- goodsList.add(goods);
- }
- for (Goods goods : goodsList) {
- System.out.println(goods);
- }
- }
- #查询别名 默认别名无法查看,默认别名同索引名
- GET goods/_alias/
- #结果
- {
- "goods" : {
- "aliases" : { }
- }
- }
- # -------重建索引-----------
- # 新建student_index_v1。索引名称必须全部小写
- PUT student_index_v1
- {
- "mappings": {
- "properties": {
- "birthday":{
- "type": "date"
- }
- }
- }
- }
- #查看 student_index_v1 结构
- GET student_index_v1
- #添加数据
- PUT student_index_v1/_doc/1
- {
- "birthday":"1999-11-11"
- }
- #查看数据
- GET student_index_v1/_search
- #添加数据
- PUT student_index_v1/_doc/1
- {
- "birthday":"1999年11月11日"
- }
- # 业务变更了,需要改变birthday字段的类型为text
- # 1. 创建新的索引 student_index_v2
- # 2. 将student_index_v1 数据拷贝到 student_index_v2
- # 创建新的索引 student_index_v2
- PUT student_index_v2
- {
- "mappings": {
- "properties": {
- "birthday":{
- "type": "text"
- }
- }
- }
- }
- # 将student_index_v1 数据拷贝到 student_index_v2
- # _reindex 拷贝数据
- POST _reindex
- {
- "source": {
- "index": "student_index_v1"
- },
- "dest": {
- "index": "student_index_v2"
- }
- }
- GET student_index_v2/_search
- PUT student_index_v2/_doc/2
- {
- "birthday":"1999年11月11日"
- }
- # 思考: 现在java代码中操作es,还是使用的实student_index_v1老的索引名称。
- # 1. 改代码(不推荐)
- # 2. 索引别名(推荐)
- # 步骤:
- # 0. 先删除student_index_v1
- # 1. 给student_index_v2起个别名 student_index_v1
- # 先删除student_index_v1
- #DELETE student_index_v1 这一操作将删除student_index_v1索引库
- #索引库默认的别名与索引库同名,无法删除
- # 给student_index_v1起个别名 student_index_v11
- POST student_index_v2/_alias/student_index_v11
- #测试删除命令
- POST /_aliases
- {
- "actions": [
- {"remove": {"index": "student_index_v1", "alias": "student_index_v11"}}
- ]
- }
- # 给student_index_v2起个别名 student_index_v1
- POST student_index_v2/_alias/student_index_v1
- #查询别名
- GET goods/_alias/
- GET student_index_v1/_search
- GET student_index_v2/_search