加入收藏 | 设为首页 | 会员中心 | 我要投稿 大连站长网 (https://www.0411zz.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 站长学院 > MySql教程 > 正文

如何使用elasticsearch创建自己的搜索系统

发布时间:2022-01-17 13:45:42 所属栏目:MySql教程 来源:互联网
导读:这期内容当中小编将会给大家带来有关如何使用elasticsearch搭建自己的搜索系统,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。 什么是elasticsearch# Elasticsearch 是一个开源的高度可扩展的全文搜索和分析引擎,拥
        这期内容当中小编将会给大家带来有关如何使用elasticsearch搭建自己的搜索系统,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。
 
什么是elasticsearch#
      Elasticsearch 是一个开源的高度可扩展的全文搜索和分析引擎,拥有查询近实时的超强性能。
 
       大名鼎鼎的Lucene 搜索引擎被广泛用于搜索领域,但是操作复杂繁琐,总是让开发者敬而远之。而 Elasticsearch将 Lucene 作为其核心来实现所有索引和搜索的功能,通过简单的 RESTful 语法来隐藏掉 Lucene 的复杂性,从而让全文搜索变得简单
 
      ES在Lucene基础上,提供了一些分布式的实现:集群,分片,复制等。
 
搜索为什么不用MySQL而用es#
我们本文案例是一个迷你商品搜索系统,为什么不考虑使用MySQL来实现搜索功能呢?原因如下:
 
MySQL默认使用innodb引擎,底层采用b+树的方式来实现,而Es底层使用倒排索引的方式实现,使用倒排索引支持各种维度的分词,可以掌控不同粒度的搜索需求。(MYSQL8版本也支持了全文检索,使用倒排索引实现,有兴趣可以去看看两者的差别)
如果使用MySQL的%key%的模糊匹配来与es的搜索进行比较,在8万数据量时他们的耗时已经达到40:1左右,毫无疑问在速度方面es完胜。
es在大厂中的应用情况#
es运用最广泛的是elk组合来对日志进行搜索分析
58安全部门、京东订单中心几乎全采用es来完成相关信息的存储与检索
es在tob的项目中也用于各种检索与分析
在c端产品中,企业通常自己基于Lucene封装自己的搜索系统,为了适配公司营销战略、推荐系统等会有更多定制化的搜索需求
es客户端选型#
spring-boot-starter-data-elasticsearch#
我相信你看到的网上各类公开课视频或者小项目均推荐使用这款springboot整合过的es客户端,但是我们要say no!
 
如何使用elasticsearch搭建自己的搜索系统
 
此图是引入的最新版本的依赖,我们可以看到它所使用的es-high-client也为6.8.7,而es7.x版本都已经更新很久了,这里许多新特性都无法使用,所以版本滞后是他最大的问题。而且它的底层也是highclient,我们操作highclient可以更灵活。我呆过的两个公司均未采用此客户端。
 
elasticsearch-rest-high-level-client#
这是官方推荐的客户端,支持最新的es,其实使用起来也很便利,因为是官方推荐所以在特性的操作上肯定优于前者。而且该客户端与TransportClient不同,不存在并发瓶颈的问题,官方首推,必为精品!
 
搭建自己的迷你搜索系统#
引入es相关依赖,除此之外需引入springboot-web依赖、jackson依赖以及lombok依赖等。
 
Copy <properties>
        <es.version>7.3.2</es.version>
    </properties>
<!-- high client-->
<dependency>
        <groupId>org.elasticsearch.client</groupId>
        <artifactId>elasticsearch-rest-high-level-client</artifactId>
        <version>${es.version}</version>
        <exclusions>
            <exclusion>
                <groupId>org.elasticsearch.client</groupId>
                <artifactId>elasticsearch-rest-client</artifactId>
            </exclusion>
            <exclusion>
                <groupId>org.elasticsearch</groupId>
                <artifactId>elasticsearch</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    <dependency>
        <groupId>org.elasticsearch</groupId>
        <artifactId>elasticsearch</artifactId>
        <version>${es.version}</version>
    </dependency>
    <!--rest low client high client以来低版本client所以需要引入-->
    <dependency>
        <groupId>org.elasticsearch.client</groupId>
        <artifactId>elasticsearch-rest-client</artifactId>
        <version>${es.version}</version>
    </dependency>
es配置文件es-config.properties
 
Copyes.host=localhost
es.port=9200
es.token=es-token
es.charset=UTF-8
es.scheme=http
es.client.connectTimeOut=5000
es.client.socketTimeout=15000
封装RestHighLevelClient
 
Copy@Configuration@PropertySource("classpath:es-config.properties")public class RestHighLevelClientConfig {    @Value("${es.host}")    private String host;    @Value("${es.port}")    private int port;    @Value("${es.scheme}")    private String scheme;    @Value("${es.token}")    private String token;    @Value("${es.charset}")    private String charSet;    @Value("${es.client.connectTimeOut}")    private int connectTimeOut;    @Value("${es.client.socketTimeout}")    private int socketTimeout;    @Bean
    public RestClientBuilder restClientBuilder() {
        RestClientBuilder restClientBuilder = RestClient.builder(                new HttpHost(host, port, scheme)
        );
        Header[] defaultHeaders = new Header[]{                new BasicHeader("Accept", "*/*"),                new BasicHeader("Charset", charSet),                //设置token 是为了安全 网关可以验证token来决定是否发起请求 我们这里只做象征性配置
                new BasicHeader("E_TOKEN", token)
        };
        restClientBuilder.setDefaultHeaders(defaultHeaders);
        restClientBuilder.setFailureListener(new RestClient.FailureListener(){            @Override
            public void onFailure(Node node) {
                System.out.println("监听某个es节点失败");
            }
        });
        restClientBuilder.setRequestConfigCallback(builder ->
                builder.setConnectTimeout(connectTimeOut).setSocketTimeout(socketTimeout));        return restClientBuilder;
    }    @Bean
    public RestHighLevelClient restHighLevelClient(RestClientBuilder restClientBuilder) {        return new RestHighLevelClient(restClientBuilder);
    }
}
封装es常用操作 es搜索系统封装源码
 
Copy@Servicepublic class RestHighLevelClientService {    
    @Autowired
    private RestHighLevelClient client;    @Autowired
    private ObjectMapper mapper;    /**
     * 创建索引
     * @param indexName
     * @param settings
     * @param mapping
     * @return
     * @throws IOException
     */
    public CreateIndexResponse createIndex(String indexName, String settings, String mapping) throws IOException {
        CreateIndexRequest request = new CreateIndexRequest(indexName);        if (null != settings && !"".equals(settings)) {
            request.settings(settings, XContentType.JSON);
        }        if (null != mapping && !"".equals(mapping)) {
            request.mapping(mapping, XContentType.JSON);
        }        return client.indices().create(request, RequestOptions.DEFAULT);
    }    /**
     * 判断 index 是否存在
     */
    public boolean indexExists(String indexName) throws IOException {
        GetIndexRequest request = new GetIndexRequest(indexName);        return client.indices().exists(request, RequestOptions.DEFAULT);
    }    
    /**
     * 搜索
    */
    public SearchResponse search(String field, String key, String rangeField, String
                                 from, String to,String termField, String termVal,
                                 String ... indexNames) throws IOException{
        SearchRequest request = new SearchRequest(indexNames);
        SearchSourceBuilder builder = new SearchSourceBuilder();
        BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
        boolQueryBuilder.must(new MatchQueryBuilder(field, key)).must(new RangeQueryBuilder(rangeField).from(from).to(to)).must(new TermQueryBuilder(termField, termVal));
        builder.query(boolQueryBuilder);
        request.source(builder);
        log.info("[搜索语句为:{}]",request.source().toString());        return client.search(request, RequestOptions.DEFAULT);
    }    /**
     * 批量导入
     * @param indexName
     * @param isAutoId 使用自动id 还是使用传入对象的id
     * @param source
     * @return
     * @throws IOException
     */
    public BulkResponse importAll(String indexName, boolean isAutoId, String  source) throws IOException{        if (0 == source.length()){            //todo 抛出异常 导入数据为空
        }
        BulkRequest request = new BulkRequest();
        JsonNode jsonNode = mapper.readTree(source);        if (jsonNode.isArray()) {            for (JsonNode node : jsonNode) {                if (isAutoId) {
                    request.add(new IndexRequest(indexName).source(node.asText(), XContentType.JSON));
                } else {
                    request.add(new IndexRequest(indexName)
                            .id(node.get("id").asText())
                            .source(node.asText(), XContentType.JSON));
                }
            }
        }        return client.bulk(request, RequestOptions.DEFAULT);
    }
创建索引,这里的settings是设置索引是否设置复制节点、设置分片个数,mappings就和数据库中的表结构一样,用来指定各个字段的类型,同时也可以设置字段是否分词(我们这里使用ik中文分词器)、采用什么分词方式。
 
Copy   @Test
    public void createIdx() throws IOException {
        String settings = "" +                "  {n" +                "      "number_of_shards" : "2",n" +                "      "number_of_replicas" : "0"n" +                "   }";
        String mappings = "" +                "{n" +                "    "properties": {n" +                "      "itemId" : {n" +                "        "type": "keyword",n" +                "        "ignore_above": 64n" +                "      },n" +                "      "urlId" : {n" +                "        "type": "keyword",n" +                "        "ignore_above": 64n" +                "      },n" +                "      "sellAddress" : {n" +                "        "type": "text",n" +                "        "analyzer": "ik_max_word", n" +                "        "search_analyzer": "ik_smart",n" +                "        "fields": {n" +                "          "keyword" : {"ignore_above" : 256, "type" : "keyword"}n" +                "        }n" +                "      },n" +                "      "courierFee" : {n" +                "        "type": "textn" +                "      },n" +                "      "promotions" : {n" +                "        "type": "text",n" +                "        "analyzer": "ik_max_word", n" +                "        "search_analyzer": "ik_smart",n" +                "        "fields": {n" +                "          "keyword" : {"ignore_above" : 256, "type" : "keyword"}n" +                "        }n" +                "      },n" +                "      "originalPrice" : {n" +                "        "type": "keyword",n" +                "        "ignore_above": 64n" +                "      },n" +                "      "startTime" : {n" +                "        "type": "date",n" +                "        "format": "yyyy-MM-dd HH:mm:ss"n" +                "      },n" +                "      "endTime" : {n" +                "        "type": "date",n" +                "        "format": "yyyy-MM-dd HH:mm:ss"n" +                "      },n" +                "      "title" : {n" +                "        "type": "text",n" +                "        "analyzer": "ik_max_word", n" +                "        "search_analyzer": "ik_smart",n" +                "        "fields": {n" +                "          "keyword" : {"ignore_above" : 256, "type" : "keyword"}n" +                "        }n" +                "      },n" +                "      "serviceGuarantee" : {n" +                "        "type": "text",n" +                "        "analyzer": "ik_max_word", n" +                "        "search_analyzer": "ik_smart",n" +                "        "fields": {n" +                "          "keyword" : {"ignore_above" : 256, "type" : "keyword"}n" +                "        }n" +                "      },n" + &nbs

(编辑:大连站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!