黑马畅购商城06-Elasticsearch

学习es可以看:狂神说es

1.概述

Elasticsearch是一个基于Lucene(java)的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口,区别于solr的webservice。

2.安装

jdk1.8 ElasticSearch客户端 界面工具(Kibana)

2.1 ElasticSearch客户端下载

官网地址 https://www.elastic.co/cn/downloads/

windows下 解压即可使用
启动 elasticsearch-7.7.0\bin\elasticsearch.bat 访问地址 localhost:9200
跨域配置 elasticsearch-7.7.0\config\elasticsearch.yml 增加如下代码

http.cors.enabled: true
http.cors.allow-origin: "*"

2.2 ES可视化工具 ES Head

官网地址 https://github.com/mobz/elasticsearch-head

#启动需要nodejs环境 启动命令 访问地址 localhost:9100

cd D:\sde\elasticsearch\elasticsearch-head-master
npm install
npm run start

当然,你可以直接下载chorm浏览器的插件

2.3 ES可视化工具 Kibana

官网地址 https://www.elastic.co/cn/downloads/

windows下 解压即可使用
启动 kibana-7.7.1-windows-x86_64\bin 访问地址 localhost:5601
#汉化 kibana-7.7.1-windows-x86_64\config\kibana.yml 增加如下代码
i18n.locale: “zh-CN”
回到顶部

3. IK分词器

官网地址 https://github.com/medcl/elasticsearch-analysis-ik/releases

解压到 D:\sde\elasticsearch\elasticsearch-7.7.0\plugins\analysis-ik 目录没有新建analysis-ik 目录名称不重要,随意起

检查是否加载分词器

cd D:\sde\elasticsearch\elasticsearch-7.7.0\bin

elasticsearch-plugin list
算法 ik_smart(最少切分) ik_max_word(最细粒度切分) 及用kibana校验 默认keywork standard

GET _analyze
{
  "analyzer": "ik_max_word",
  "text": ["美国民主党"]
}
GET _analyze
{
"analyzer": "ik_smart",
"text": ["美国民主党"]
}

扩充字典(人名、网络流行语)

4. Kibana 基本语法 API

methodurldesc
PUTlocalhost:9200/索引名称/类型名称/文档id创建文档(指定文档id)
POSTlocalhost:9200/索引名称/类型名称创建文档(随机id)
POSTlocalhost:9200/索引名称/_update/文档id修改文档
DELETElocalhost:9200/索引名称/类型名称/文档id删除文档 by id
GETlocalhost:9200/索引名称/类型名称/文档id查询文档 by id
POSTlocalhost:9200/索引名称/_search查询所有文档

4.1 新建

#创建空库
PUT /test2
{
    
}
#创建索引 及 规定字段类型
PUT /test3
{
  "mappings": {
    "properties": {
      "name":{
        "type": "text"
      },
      "age":{
        "type": "integer"
      },
      "birth":{
        "type": "date"
      }
    }
  }
}
#创建数据
PUT /wanghl/_doc/2
{
  "name":"花木兰",
  "age":67,
  "tags":["战士","上单","女"]
}


4.2 删除
#删除索引
DELETE test2
#删除文档
DELETE test1/_doc/3
4.3修改
#修改文档
POST /test1/_update/4
{
   "doc":{
     "name":"红桃A"
   }
}

4.4 查询

#获取索引库
GET test3
#获取文档by文档id
GET wanghl/_doc/2
#根据属性查询  简写
GET wanghl/_search?q=name:李
#构建式查询   
#_source    字段过滤   不写默认 select  *
# from  size   分页
GET /wanghl/_search
{
  "query": {
    "match": {
      "tags": "男"
    }
  },
  "_source": ["name","tags"], 
  "from":0,
  "size":1
}
#多条件查询   must 相当于 and     should 相当于 or     
GET wanghl/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "tags": "男 下路"
          }
        }
      ],
      "must_not": [
        {
          "match": {
            "age": "3"
          }
        }
      ]
    }
  }
}
# 查询过滤  +  高亮显示
GET wanghl/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "tags": "男"
          }
        }
      ] ,
      "filter": [
        {
          "range": {
            "age": {
              "gte": 10,
              "lte": 200
            }
          }
        }
      ]  
    }
  },
  "highlight": {
    "pre_tags": "<font>",
    "post_tags": "</font>", 
    "fields": {
      "tags": {}
    }
  }
}

5.SpringBoot集成 ES(商城中的应用)

5.1创建changgou_service_search模块,pom.xml引入依赖

pom文件添加依赖

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>

所有依赖

<dependency>
    <groupId>com.changgou</groupId>
    <artifactId>changgou_common</artifactId>
    <version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
<dependency>
    <groupId>com.changgou</groupId>
    <artifactId>changgou_service_goods_api</artifactId>
    <version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
    <groupId>com.changgou</groupId>
    <artifactId>changgou_service_search_api</artifactId>
    <version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-amqp</artifactId>
</dependency>

5.2 changgou_service_search的application.yml

spring:
	data:
		elasticsearch:
      		cluster-name: elasticsearch
      		cluster-nodes: 192.168.200.128:9300
server:
  port: 9009
spring:
  application:
    name: search
  rabbitmq:
    host: 192.168.200.128
  redis:
    host: 192.168.200.128
  main:
    allow-bean-definition-overriding: true #当遇到同样名字的时候,是否允许覆盖注册
  data:
    elasticsearch:
      cluster-name: elasticsearch
      cluster-nodes: 192.168.200.128:9300
eureka:
  client:
    service-url:
      defaultZone: http://127.0.0.1:6868/eureka
  instance:
    prefer-ip-address: true
feign:
  hystrix:
    enabled: true
  client:
    config:
      default:   #配置全局的feign的调用超时时间  如果 有指定的服务配置 默认的配置不会生效
        connectTimeout: 600000 # 指定的是 消费者 连接服务提供者的连接超时时间 是否能连接  单位是毫秒
        readTimeout: 600000  # 指定的是调用服务提供者的 服务 的超时时间()  单位是毫秒
#hystrix 配置
hystrix:
  command:
    default:
      execution:
        timeout:
          #如果enabled设置为false,则请求超时交给ribbon控制
          enabled: false
        isolation:
          strategy: SEMAPHORE

狂神说中需注册es client对象

package com.nesc.esapi.config;

import org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * 定义高版本ES实例对象
 * @author wanghl
 * @date 2020/7/17 9:23
 **/
@Configuration
public class ElasticSearchClientConfig {

    @Bean
    public RestHighLevelClient restHighLevelClient() {
        RestHighLevelClient client = new RestHighLevelClient(
                RestClient.builder(
                        new HttpHost("127.0.0.1", 9200, "http")
                )
        );
        return client;
    }
}

测试类

package com.nesc.esapi;

import com.alibaba.fastjson.JSONObject;
import com.nesc.esapi.domain.User;
import lombok.SneakyThrows;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.client.indices.CreateIndexResponse;
import org.elasticsearch.client.indices.GetIndexRequest;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.MatchQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.FetchSourceContext;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.io.IOException;
import java.util.ArrayList;

/**
 * ES client api测试
 */
@SpringBootTest
class EsApiApplicationTests {

    @Autowired
    RestHighLevelClient restHighLevelClient;

    /**
     * 新建索引
     * @throws Exception
     */
    @Test
    void testCreateIndex() throws IOException {
        //创建请求
        CreateIndexRequest request = new CreateIndexRequest("testapi");
        CreateIndexResponse createIndexResponse = restHighLevelClient.indices().create(request,RequestOptions.DEFAULT);
    }

    /**
     * 查询索引
     * @throws IOException
     */
    @Test
    void testExistIndex() throws IOException {
        GetIndexRequest request = new GetIndexRequest("testapi");
        boolean exists = restHighLevelClient.indices().exists(request, RequestOptions.DEFAULT);
        System.out.println(exists);
    }

    /**
     * 删除索引
     * @throws IOException
     */
    @Test
    void testDeleteIndex() throws IOException {
        DeleteIndexRequest deleteIndexRequest = new DeleteIndexRequest("testapi");
        AcknowledgedResponse delete = restHighLevelClient.indices().delete(deleteIndexRequest, RequestOptions.DEFAULT);
        System.out.println(delete);
    }

    /**
     * 创建文档
     * @throws IOException
     */
    @Test
    void testCreateDocument() throws IOException {
        IndexRequest indexRequest = new IndexRequest("testapi");
        User user = new User("张飞","射手");
        IndexRequest source = indexRequest.source(JSONObject.toJSONString(user), XContentType.JSON);
        IndexResponse index = restHighLevelClient.index(indexRequest, RequestOptions.DEFAULT);
        System.out.println(index.toString());
    }

    /**
     * 文档是否存在
     * @throws IOException
     */
    @Test
    void testExistDocument() throws IOException {
        //testapi 索引中     是否存在 1 的文档
        GetRequest getRequest = new GetRequest("testapi", "1");
        boolean exists = restHighLevelClient.exists(getRequest, RequestOptions.DEFAULT);
        System.out.println(exists);
    }

    /**
     * 获取文档信息
     * @throws IOException
     */
    @Test
    void testGetDocument() throws IOException {
        GetRequest getRequest = new GetRequest("testapi", "gBd0W3MBYL0QvcF5Z9tv");
        GetResponse documentFields = restHighLevelClient.get(getRequest, RequestOptions.DEFAULT);
        System.out.println(documentFields.getSource());
    }

    /**
     * 获取文档信息
     * @throws IOException
     */
    @Test
    void testUpdatDocument() throws IOException {
        UpdateRequest updateRequest = new UpdateRequest("testapi", "jxeBW3MBYL0QvcF5idvD");
        User user = new User("张飞","坦克");
        updateRequest.doc(JSONObject.toJSONString(user),XContentType.JSON);
        UpdateResponse update = restHighLevelClient.update(updateRequest, RequestOptions.DEFAULT);
        System.out.println(update.status());
    }

    /**
     * 删除文档信息
     * @throws IOException
     */
    @Test
    void testDeleteDocument() throws IOException {
        DeleteRequest deleteRequest = new DeleteRequest("testapi", "jxeBW3MBYL0QvcF5idvD");
        DeleteResponse delete = restHighLevelClient.delete(deleteRequest, RequestOptions.DEFAULT);
        System.out.println(delete.status());
    }

    /**
     * 查询文档
     */
    @Test
    void testSearchDocument() throws IOException {
        SearchRequest searchRequest = new SearchRequest("testapi");
        //匹配字段
        MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("username", "李白");
        //构建查询器
        searchRequest.source(new SearchSourceBuilder().query(matchQueryBuilder));
        SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        System.out.println(searchResponse.getHits().getTotalHits());
    }
// 批量插入
    @Test
    void bulkDocument() throws IOException {
        ArrayList<User> users = new ArrayList<>();
        users.add(new User("aa", 10));
        users.add(new User("bb", 11));
        users.add(new User("cc", 12));
        BulkRequest bulkRequest = new BulkRequest();
        bulkRequest.timeout("10s");
        for (int i = 0; i < users.size(); i++) {
            bulkRequest.add(new IndexRequest("wuf_index").id("" + (i + 1)).source(JSON.toJSONString(users.get(i)),XContentType.JSON));
        }

        BulkResponse bulk = restHighLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT);
        System.out.println(bulk);
        System.out.println(bulk.status());
        System.out.println(bulk.hasFailures()); // 返回false代表成功
    }
//org.elasticsearch.action.bulk.BulkResponse@1f39269d
//OK
//false


    // 查询
    @Test
    void search() throws IOException {
        // 查询请求
        SearchRequest searchRequest = new SearchRequest("wuf_index");
        // 查询构造
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        // 查询条件 1和2
//		TermQueryBuilder  termQueryBuilder =  QueryBuilders.termQuery("name","aa");
        QueryBuilder termQueryBuilder = new TermQueryBuilder("name", "aa");
//		searchSourceBuilder.highlighter();
        searchSourceBuilder.query(termQueryBuilder);
        searchSourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
        searchRequest.source(searchSourceBuilder);
        SearchResponse search = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        System.out.println(search);

        System.out.println(JSON.toJSONString(search.getHits()));
        System.out.println("----------------------------------");
        for (SearchHit hit : search.getHits()) {
            System.out.println(hit.getSourceAsMap());
        }
        System.out.println("===========================================");
        for (SearchHit hit : search.getHits().getHits()) {
            System.out.println(hit.getSourceAsMap());
        }
    }
    //{"took":12,"timed_out":false,"_shards":{"total":1,"successful":1,"skipped":0,"failed":0},"hits":{"total":{"value":1,"relation":"eq"},"max_score":0.9808291,"hits":[{"_index":"zgc_index","_type":"_doc","_id":"1","_score":0.9808291,"_source":{"age":10,"name":"aa"}}]}}
    //{"fragment":true,"hits":[{"fields":{},"fragment":false,"highlightFields":{"$ref":"$.hits[0].fields"},"id":"1","matchedQueries":[],"primaryTerm":0,"rawSortValues":[],"score":0.9808291,"seqNo":-2,"sortValues":[],"sourceAsMap":{"name":"aa","age":10},"sourceAsString":"{\"age\":10,\"name\":\"aa\"}","sourceRef":{"fragment":true},"type":"_doc","version":-1}],"maxScore":0.9808291,"totalHits":{"relation":"EQUAL_TO","value":1}}
    //----------------------------------
    //{name=aa, age=10}
    //===========================================
    //{name=aa, age=10}


}

黑马的应用

创建和ES索引库映射实体类SkuInfo.java

@Document(indexName = "skuinfo", type = "docs")
public class SkuInfo implements Serializable {
    //商品id,同时也是商品编号
    @Id
    @Field(index = true, store = true, type = FieldType.Keyword)
    private Long id;

    //SKU名称
    @Field(index = true, store = true, type = FieldType.Text, analyzer = "ik_smart")
    private String name;

    //商品价格,单位为:元
    @Field(index = true, store = true, type = FieldType.Double)
    private Long price;

    //库存数量
    @Field(index = true, store = true, type = FieldType.Integer)
    private Integer num;

    //商品图片
    @Field(index = false, store = true, type = FieldType.Text)
    private String image;

    //商品状态,1-正常,2-下架,3-删除
    @Field(index = true, store = true, type = FieldType.Keyword)
    private String status;

    //创建时间
    private Date createTime;

    //更新时间
    private Date updateTime;

    //是否默认
    @Field(index = true, store = true, type = FieldType.Keyword)
    private String isDefault;

    //SPUID
    @Field(index = true, store = true, type = FieldType.Long)
    private Long spuId;

    //类目ID
    @Field(index = true, store = true, type = FieldType.Long)
    private Long categoryId;

    //类目名称
    @Field(index = true, store = true,type = FieldType.Keyword)
    private String categoryName;

    //品牌名称
    @Field(index = true, store = true,type = FieldType.Keyword)
    private String brandName;

    //规格
    private String spec;

    //规格参数
    private Map<String, Object> specMap;
    
    ......get和set方法......

创建ES操作的Dao接口

public interface SearchMapper extends ElasticsearchRepository<SkuInfo,Long> {

}

将商品信息导入(主要根据SearchMapper操作数据,ElasticsearchTemplate操作索引)

@Service
public class EsManagerServiceImpl implements EsManagerService {

    @Autowired
    private SearchMapper searchMapper;

    @Autowired
    private SkuFeign skuFeign;

    @Autowired
    private ElasticsearchTemplate esTemplate;


    /**
     * 创建索引库结构
     */
    @Override
    public void createIndexAndMapping() {
        //创建索引
        esTemplate.createIndex(SkuInfo.class);
        //创建映射
        esTemplate.putMapping(SkuInfo.class);
    }

    /**
     * 根据spuid导入数据到ES索引库
     * @param spuId 商品id
     */
    @Override
    public void importDataToESBySpuId(String spuId) {
        List<Sku> skuList = skuFeign.findSkuListBySpuId(spuId);
        List<SkuInfo> skuInfos = JSON.parseArray(JSON.toJSONString(skuList), SkuInfo.class);

        for (SkuInfo skuInfo : skuInfos) {
            skuInfo.setSpecMap(JSON.parseObject(skuInfo.getSpec(), Map.class));
        }


        searchMapper.saveAll(skuInfos);
    }

    /**
     * 导入全部数据到ES索引库
     */
    @Override
    public void importAll() {
        Map paramMap = new HashMap();
        paramMap.put("status", "1");
        Result result = skuFeign.findList(paramMap);
        List<SkuInfo> skuInfos = JSON.parseArray(JSON.toJSONString(result.getData()), SkuInfo.class);
        for (SkuInfo skuInfo : skuInfos) {
            skuInfo.setPrice(skuInfo.getPrice());
            skuInfo.setSpecMap(JSON.parseObject(skuInfo.getSpec(), Map.class));
        }
        searchMapper.saveAll(skuInfos);
    }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值