1 ElasticSearch高级操作
1.1 bulk批量操作-脚本
脚本:
测试用的5号文档
POST /person1/_doc/5 { "name":"张三5号", "age":18, "address":"北京海淀区" }
批量操作文本
#批量操作 #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号"}}
结果
{ "took" : 51, "errors" : true, "items" : [ { "delete" : { "_index" : "person1", "_type" : "_doc", "_id" : "5", "_version" : 2, "result" : "deleted", "_shards" : { "total" : 2, "successful" : 1, "failed" : 0 }, "_seq_no" : 6, "_primary_term" : 2, "status" : 200 } }, { "create" : { "_index" : "person1", "_type" : "_doc", "_id" : "8", "_version" : 1, "result" : "created", "_shards" : { "total" : 2, "successful" : 1, "failed" : 0 }, "_seq_no" : 7, "_primary_term" : 2, "status" : 201 } }, { "update" : { "_index" : "person1", "_type" : "_doc", "_id" : "2", "_version" : 2, "result" : "updated", "_shards" : { "total" : 2, "successful" : 1, "failed" : 0 }, "_seq_no" : 10, "_primary_term" : 2, "status" : 200 } } ] }
1.2 bulk批量操作-JavaAPI
/** * 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<String, Object> map=new HashMap<>(); map.put("name","六号"); IndexRequest indexRequest=new IndexRequest("person1").id("6").source(map); bulkRequest.add(indexRequest); //3. 修改3号记录 名称为 “三号” Map<String, Object> 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()); }
1.3 导入数据-分析&创建索引
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" } } } }
1.4 导入数据-代码实现
package com.itheima.elasticsearchdemo2.domain; import com.alibaba.fastjson.annotation.JSONField; import java.util.Date; import java.util.Map; public class Goods { private int id; private String title; private double price; private int stock; private int saleNum; private Date createTime; private String categoryName; private String brandName; private Map spec; @JSONField(serialize = false)//在转换JSON时,忽略该字段 private String specStr;//接收数据库的信息 "{}" public int getId() { return id; } public void setId(int id) { this.id = id; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public double getPrice() { return price; } public void setPrice(double price) { this.price = price; } public int getStock() { return stock; } public void setStock(int stock) { this.stock = stock; } public int getSaleNum() { return saleNum; } public void setSaleNum(int saleNum) { this.saleNum = saleNum; } public Date getCreateTime() { return createTime; } public void setCreateTime(Date createTime) { this.createTime = createTime; } public String getCategoryName() { return categoryName; } public void setCategoryName(String categoryName) { this.categoryName = categoryName; } public String getBrandName() { return brandName; } public void setBrandName(String brandName) { this.brandName = brandName; } public Map getSpec() { return spec; } public void setSpec(Map spec) { this.spec = spec; } public String getSpecStr() { return specStr; } public void setSpecStr(String specStr) { this.specStr = specStr; } @Override public String toString() { return "Goods{" + "id=" + id + ", title='" + title + '\'' + ", price=" + price + ", stock=" + stock + ", saleNum=" + saleNum + ", createTime=" + createTime + ", categoryName='" + categoryName + '\'' + ", brandName='" + brandName + '\'' + ", spec=" + spec + ", specStr='" + specStr + '\'' + '}'; } }
package com.itheima.elasticsearchdemo2.mapper; import com.itheima.elasticsearchdemo2.domain.Goods; import org.apache.ibatis.annotations.Mapper; import org.springframework.stereotype.Repository; import java.util.List; @Repository @Mapper public interface GoodsMapper { /** * 查询所有 */ public List<Goods> findAll(); }
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.itheima.elasticsearchdemo2.mapper.GoodsMapper"> <select id="findAll" resultType="goods"> select `id` , `title` , `price` , `stock` , `saleNum` , `createTime` , `categoryName`, `brandName` , `spec` as specStr from goods </select> </mapper>
/** * 从Mysql 批量导入 elasticSearch */ @Test public void test3() throws IOException { //1.查询所有数据,mysql List<Goods> 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()); }
1.5 导入数据-代码实现-详解
转换成JSON的原因:
#spec配置的数据类型是JSON对象,所以当存放字符串的时候报错 "spec": { "type": "object" },
错误信息
2 ElasticSearch查询
2.1 matchAll-脚本
# 默认情况下,es一次展示10条数据,通过from和size来控制分页 # 查询结果详解 GET goods/_search { "query": { "match_all": {} }, "from": 0, "size": 100 } GET goods
2.2 matchAll获取总记录数查询所有对象-JavaAPI
/** * 查询所有 * 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<Goods> 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); } }
设置条件的疑问点
2.3 termQuery 词条查询查询具体的词组不副词
term查询和字段类型有关系,首先回顾一下ElasticSearch两个数据类型
ElasticSearch两个数据类型
text:会分词,不支持聚合 keyword:不会分词,将全部内容作为一个词条,支持聚合
term查询:不会对查询条件进行分词。
GET goods/_search { "query": { "term": { "title": { "value": "华为" } } } }
term查询,查询text类型字段时,只有其中的单词相匹配都会查到,text字段会对数据进行分词
例如:查询title 为“华为”的,title type 为text
查询categoryName 字段时,categoryName字段为keyword ,keyword:不会分词,将全部内容作为一个词条,
即完全匹配,才能查询出结果
GET goods/_search { "query": { "term": { "categoryName": { "value": "华为手机" } } } }