首先在模块中添加search模块(搜索)
service-goods(商品)
service-search(搜索)
service-wms(仓储)
加入依赖
7.4.2 org.elasticsearch.client elasticsearch-rest-high-level-client7.4.2
创建几个包
创建ES的配置类ElasticSearchConfig
@Configuration @ConfigurationProperties(prefix = "es") @Setter public class ElasticSearchConfig { private String hostname; private int port; private String protocol; //请求的一些选项 public static final RequestOptions COMMON_OPTIONS; static{ RequestOptions.Builder builder=RequestOptions.DEFAULT.toBuilder(); COMMON_OPTIONS=builder.build(); } @Bean public RestHighLevelClient restHighLevelClient(){ RestClientBuilder restClientBuilder= RestClient.builder(new HttpHost(hostname,port,protocol)); RestHighLevelClient restHighLevelClient= new RestHighLevelClient(restClientBuilder); return restHighLevelClient; } }在创建ES的工具类 可以直接调用其中的我封装好的方法
- 索引ES保存数据
- 主键新增的数据
- 根据ID删除单条记录
- 更新数据
- 根据ID从ES中查询数据
- 查选条件构造器
- 使用form+size的方式实现ES分页查询
- 使用scroll实现ES分页查询
@Component @Slf4j public class ESUtil { @Resource private RestHighLevelClient restHighLevelClient; public实体类boolean saveBatch(String index,List bachList){ BulkRequest bulkRequest=new BulkRequest(); //封装保存的数据 for(int i=0;i T select(String index,String id, Class targetClass){ SearchRequest searchRequest=new SearchRequest(); searchRequest.indices(index); //构建查询条件 SearchSourceBuilder searchSourceBuilder=new SearchSourceBuilder(); searchSourceBuilder.query(QueryBuilders.termQuery("_id",id)); searchRequest.source(searchSourceBuilder); try { SearchResponse searchResponse= restHighLevelClient.search(searchRequest,ElasticSearchConfig.COMMON_OPTIONS); SearchHits hits= searchResponse.getHits(); SearchHit [] searchHits= hits.getHits(); //查询结果 if(searchHits==null||searchHits.length==0){ //如果数组为空,表示没有查询结果 return null; } String jsonString= searchHits[0].getSourceAsString(); T t= JSON.parseObject(jsonString,targetClass); return t; } catch (IOException e) { e.printStackTrace(); } return null; } public List select(String index,Class targetClass, SearchSourceBuilder searchSourceBuilder){ SearchRequest searchRequest=new SearchRequest(); //查询请求 searchRequest.indices(index); searchRequest.source(searchSourceBuilder); //请求中添加中查询条件 List list=new ArrayList<>(); try { //执行查询,获得查询结果 SearchResponse searchResponse= restHighLevelClient.search(searchRequest,ElasticSearchConfig.COMMON_OPTIONS); SearchHits hits= searchResponse.getHits(); //封装结果 SearchHit[] searchHits= hits.getHits(); for(SearchHit searchHit:searchHits){ String jsonString= searchHit.getSourceAsString(); T t=JSON.parseObject(jsonString,targetClass); list.add(t); } } catch (IOException e) { e.printStackTrace(); } return list; } public Map page(String index, SearchSourceBuilder searchSourceBuilder, Class targetClass,int from,int size){ SearchRequest searchRequest=new SearchRequest(); searchRequest.indices(index); searchSourceBuilder.from(from); searchSourceBuilder.size(size); searchRequest.source(searchSourceBuilder); Map result=new HashMap<>(); List resultList=new ArrayList<>(); int page=0; try { SearchResponse searchResponse= restHighLevelClient.search(searchRequest,ElasticSearchConfig.COMMON_OPTIONS); SearchHits hits= searchResponse.getHits(); long totalValue=hits.getTotalHits().value; //获得总记录数 3.0/2=1.5 Math.ceil(1.5) 2.0; page = (int) Math.ceil((double)totalValue/size); //总页数 SearchHit [] searchHits= hits.getHits(); for(SearchHit searchHit:searchHits){ String jsonString= searchHit.getSourceAsString(); T t= JSON.parseObject(jsonString,targetClass); resultList.add(t); } } catch (IOException e) { e.printStackTrace(); } result.put("page",page); result.put("list",resultList); return result; } public Map page(String index, SearchSourceBuilder searchSourceBuilder, Class targetClass,int size,String scrollId){ SearchRequest searchRequest=new SearchRequest(); searchRequest.indices(index); Scroll scroll=new Scroll(Timevalue.timevalueMinutes(1)); //指定scroll镜像的时间为1分钟 searchSourceBuilder.size(size); //每页显示多少条记录 Map map=new HashMap<>(); SearchResponse searchResponse=null; try { if(StringUtils.isBlank(scrollId)){ //scroll方式的第一次查询 searchRequest.scroll(scroll); //查询是scroll查询 镜像的时间为1分钟 searchRequest.source(searchSourceBuilder); //查询请求中添加查询条件 searchResponse=restHighLevelClient.search(searchRequest,ElasticSearchConfig.COMMON_OPTIONS); }else{ //scroll方式的后面查询 请求:GET /_search/scroll SearchScrollRequest searchScrollRequest=new SearchScrollRequest(); searchScrollRequest.scroll(scroll); searchScrollRequest.scrollId(scrollId); searchResponse=restHighLevelClient.scroll(searchScrollRequest,ElasticSearchConfig.COMMON_OPTIONS); } //封装查询结果 map= searchResponseToMap(searchResponse,size,targetClass); } catch (IOException e) { e.printStackTrace(); } return map; } //当前页的数据 scrollId 总页数 private Map searchResponseToMap(SearchResponse searchResponse,int size,Class targetClass){ SearchHits hits= searchResponse.getHits(); //查询的结果 double count=hits.getTotalHits().value; //获得总记录数 int page= (int)Math.ceil(count/size); //算出总页数 Map map=new HashMap<>(); //返回的结果 List list=new ArrayList<>(); //当前页的数据 SearchHit [] searchHits= hits.getHits(); //获得hits中的数据 for(SearchHit temp:searchHits){ String jsonString= temp.getSourceAsString(); T t=JSON.parseObject(jsonString,targetClass); list.add(t); } map.put("page",page); map.put("scrollId",searchResponse.getScrollId()); map.put("list",list); return map; } }
@Getter @Setter @AllArgsConstructor @NoArgsConstructor @Builder public class Company { private String name; private String job; private String logo; private Double payment; @Override public String toString() { return "name:"+name+",job:"+job+",logo:"+logo+",payment:"+payment; } }yml文件
es: hostname: 外网IP/本地IP port: 9200 protocol: http启动类
写完之后我们可以先用测试类测试
添加@Test public void testSave(){ Company company= Company.builder().name("广坤").job("东北F4") .logo("DBF4").payment(20000.0).build(); List删除companyList=new ArrayList<>(); companyList.add(company); companyList.add(company); companyList.add(company); esUtil.saveBatch("company-index",companyList); }
@Test public void testDelete(){ esUtil.deleteById("company-index","5"); }修改
@Test public void testUpdate(){ Company company= Company.builder().name("广坤").job("东北F4") .logo("DBF4").payment(20000.0).build(); String jsonString=JSONObject.toJSonString(company); esUtil.updateById("company-index","4",jsonString); }按ID查询
@Test public void testQueryId(){ Company company= esUtil.select("company-index","1000",Company.class); System.out.println(company+"!!!!!!!!!!!"); }查询(from+size)
@Test public void testQuery(){ SearchSourceBuilder searchSourceBuilder=new SearchSourceBuilder(); // searchSourceBuilder.query(QueryBuilders.matchQuery("name","scott")); List查询(scrollID)companyList= esUtil.select("company-index",Company.class,searchSourceBuilder); for(Company temp:companyList){ System.out.println(temp.getName()); } }
@Test public void testPage2(){ SearchSourceBuilder searchSourceBuilder=new SearchSourceBuilder(); Mapmap= esUtil.page("company-index", searchSourceBuilder,Company.class,2,"DXF1ZXJ5QW5kRmV0Y2gBAAAAAAAFSu4WMlRKYnQzcW1RMDJBeVhnODF6ekxTQQ=="); int page=(int)map.get("page"); List companyList=(List )map.get("list"); String scrollId=(String)map.get("scrollId"); System.out.println("总页数:"+page); System.out.println("每页的数据:"+companyList.size()); System.out.println(scrollId); }
全部测试完 没有问题 下面可以去kibanna写DSL语句
创建索引 修改映射
PUT goods-index { "mappings" : { "properties" : { "brandId" : { "type" : "long" }, "brandImg" : { "type" : "text", "fields" : { "keyword" : { "type" : "keyword", "ignore_above" : 256 } } }, "brandName" : { "type" : "text", "fields" : { "keyword" : { "type" : "keyword", "ignore_above" : 256 } } }, "catalogId" : { "type" : "long" }, "categoryName" : { "type" : "text", "fields" : { "keyword" : { "type" : "keyword", "ignore_above" : 256 } } }, "hasStock" : { "type" : "boolean" }, "hotScore" : { "type" : "long" }, "list" : { "type" : "nested", "properties" : { "attrName" : { "type" : "keyword", "fields" : { "keyword" : { "type" : "keyword", "ignore_above" : 256 } } }, "attrValue" : { "type" : "keyword", "fields" : { "keyword" : { "type" : "keyword", "ignore_above" : 256 } } }, "skuId" : { "type" : "long" } } }, "saleCount" : { "type" : "long" }, "skuId" : { "type" : "long" }, "skuImg" : { "type" : "text", "fields" : { "keyword" : { "type" : "keyword", "ignore_above" : 256 } } }, "skuPrice" : { "type" : "long" }, "skuTitle" : { "type" : "text", "fields" : { "keyword" : { "type" : "keyword", "ignore_above" : 256 } } }, "spuId" : { "type" : "long" } } } } }
有些类型需要改成keyword
查看映射
GET /goods-index/_mapping
查数据 写出DSL语句才好在java中实现
GET /goods-index/_search { "query": { "bool": { "must": [ { "multi_match": { "query": "华为", "fields": [ "brandName", "skuTitle" ] } } ], "filter": [ { "term": { "catalogId": "225" } }, { "term": { "brandId": "5" } }, { "nested": { "path": "list", "query": { "bool": { "must": [ { "match": { "list.attrName": "颜色" } }, { "match": { "list.attrValue": "星河银" } } ] } } } } ] } }, "from": 0, "size": 2, "sort": [ { "hotScore": { "order": "desc" } } ] }
解释:
- 使用ESmulti_match查询 query: "华为" 查询的字段是fields:brandName,skuTitle根据这两个字段查询出带有华为的数据
- filter term过滤出 catalogId = 225 term brandId=5
- nested 是类型是对象数据类型的专用版本,它允许对象数组以可以彼此独立查询的方式进行索引。path:集合字段名。一个match相当于list集合中一个字段名list.attrName ="颜色"list.attrValue="星河银"
- from 从第几条开始 size一页展示多少条
- sort排序 根据什么字段进行排序,order=desc 倒排
ES中拿到数据 我们现在去java开始编写代码
@PostMapping("/search") public QueryResult queryResultSearch(@RequestBody SearchQueryParam searchQueryParam) { SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery(); //转类型 String sortName = searchQueryParam.getSortName(); String sortValue = searchQueryParam.getSortValue(); String keyWord = searchQueryParam.getKeyWord(); Integer brandId = searchQueryParam.getBrandId(); Integer categoryId = searchQueryParam.getCategoryId(); ListattrList = searchQueryParam.getAttrList(); //排序sort if (!StringUtils.isNotEmpty(sortName) && (!StringUtils.isNotEmpty(sortValue) && searchQueryParam.getSortValue().equals("asc"))) { searchSourceBuilder.sort(searchQueryParam.getSortName(), SortOrder.ASC); } if (!StringUtils.isNotEmpty(sortName) && (!StringUtils.isNotEmpty(sortValue) && searchQueryParam.getSortValue().equals("desc"))) { searchSourceBuilder.sort(searchQueryParam.getSortName(), SortOrder.DESC); } int size = 2; int from = (searchQueryParam.getCurrentPage() - 1) * size; //搜索框 if (!StringUtils.isNotEmpty(keyWord)) { boolQueryBuilder.must(QueryBuilders.multiMatchQuery(keyWord, "brandName", "skuTitle")); } //filter 属性 if (brandId != 0 || brandId != null) { boolQueryBuilder.filter(QueryBuilders.termQuery("brandId", brandId)); } if (categoryId != 0 || categoryId != null) { boolQueryBuilder.filter(QueryBuilders.termQuery("catalogId", categoryId)); } //list类型 nested for (SearchQueryParam.Attr attr : attrList) { BoolQueryBuilder boolQueryBuilder1 = QueryBuilders.boolQuery(); List must = boolQueryBuilder1.must(); must.add(QueryBuilders.matchQuery("list.attrName", attr.getAttrName())); must.add(QueryBuilders.matchQuery("list.attrValue", attr.getAttrValue())); boolQueryBuilder.filter(QueryBuilders.nestedQuery("list", boolQueryBuilder1, ScoreMode.None)); } searchSourceBuilder.query(boolQueryBuilder); Map page = esUtil.page("goods-index", searchSourceBuilder, SkuEsDTO.class, from, size); List list = (List ) page.get("list"); System.out.println("元素个数:" + list.size()); //这里开始方法 封装 ES代码到这里结束!!!! SearchSourceBuilder searchSourceBuilder1 = new SearchSourceBuilder(); List select = esUtil.select("goods-index", SkuEsDTO.class, searchSourceBuilder1); System.out.println("select :" + select.size()); QueryResult queryResult = new QueryResult(); HashSet attrHashSet = new HashSet<>(); //BrandVo添加数据 for (SkuEsDTO skuEsDTO : select) { Attr attr1 = new Attr(); queryResult = new QueryResult(); BrandVo brandVo = new BrandVo(); String brandName = skuEsDTO.getBrandName(); Long brandIdOne = skuEsDTO.getBrandId(); //brandVo添加数据 brandVo.setId(brandIdOne.intValue()); brandVo.setName(brandName); queryResult.getBrandVo().add(brandVo); //Catalog添加数据 CategoryVo categoryVo = new CategoryVo(); Long catalogId = skuEsDTO.getCatalogId(); String categoryName = skuEsDTO.getCategoryName(); categoryVo.setCatalogId(catalogId.intValue()); categoryVo.setCategoryName(categoryName); queryResult.getCategoryVoList().add(categoryVo); //list 颜色 for (SkuEsDTO.Attr attr : skuEsDTO.getList()) { String attrName = attr.getAttrName(); String attrValue = attr.getAttrValue(); attr1.setAttrValue(attrValue); attrHashSet.add(attr1); queryResult.getAttrsMap().put(attrName, attrHashSet); } } queryResult.setTotalPage(select.size()); queryResult.setSkuEsDTOList(list); return queryResult; }
swagger 测试
{ "attrList": [ { "attrName": "颜色", "attrValue": "星河银", "skuId": 1 } ], "brandId": 5, "categoryId": 225, "currentPage": 1, "keyWord": "华为", "sortName": "hotScore", "sortValue": "desc" }展示成功!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)