ElasticSearch与Solr对比

环境说明

操作系统:windows10

安装、配置

ElasticSearch

第一步:下载

下载:官网下载地址

第二步:解压运行

解压zip 并进入bin目录下 双击elasticsearch.bat 运行

第三步:查看是否运行成功

访问 http://localhost:9200/

地址
请添加图片描述

出现该界面说明运行成功

无需其他配置 其余可以在springboot集成时进行相应操作

第四步:ik分词器

下载对应版本的ik分词器包后 在es安装目录\plugins下新建ik文件夹 将下载好的ik zip包解压到该目录下

分词效果 其中 ik_smart 为最少切分,ik_max_word为最细粒度划分

ik_smart : 将一个中文字符串进行最少的单词切分:

ik_max_word : 将一个中文字符串进行尽可能多的单词切分:

请添加图片描述

第五步:创建索引并指定默认分词

请添加图片描述

{"settings":{"index":{"analysis.analyzer.default.type":"ik_max_word"}}}

Solr

第一步:下载

官网下载地址

第二步:解压运行

解压后运行cmd进入bin目录执行 solr start命令 (solr restart -p 8983重启命令)

请添加图片描述

第三步:查看是否运行成功

浏览器进入 http://localhost:8983/solr

地址

请添加图片描述

第四步:创建core(可以理解为数据库)

solr create -c “core名称”

第五步:注册字段


进入G:\solr\solr-8.9.0\server\solr\demo-core\conf

demo-core 为创建的core名称

进行字段配置

  <field name="cityCode" type="string" indexed="true" stored="true"/>
	<field name="code" type="string" indexed="true" stored="true"/>
	<field name="firstChar" type="string" indexed="true" stored="true"/>
	<field name="jianPin" type="string" indexed="true" stored="true"/>
	...

第六步:配置IK分词器


下载地址

将下载好的jar包放入\server\solr-webapp\webapp\WEB-INF\lib 下

然后配置managed-schema中添加ik分词器的配置(\server\solr\demo-core\conf)

<fieldType name="ik_word" class="solr.TextField">
  <analyzer type="index">
      <tokenizer class="org.wltea.analyzer.lucene.IKTokenizerFactory" useSmart="false" conf="ik.conf"/>
      <filter class="solr.LowerCaseFilterFactory"/>
  </analyzer>
  <analyzer type="query">
      <tokenizer class="org.wltea.analyzer.lucene.IKTokenizerFactory" useSmart="true" conf="ik.conf"/>
      <filter class="solr.LowerCaseFilterFactory"/>
  </analyzer>
</fieldType>

将字段配置中的type改为 ik_word

  <field name="cityCode" type="string" indexed="true" stored="true"/>
	<field name="code" type="string" indexed="true" stored="true"/>
	<field name="firstChar" type="string" indexed="true" stored="true"/>
	<field name="jianPin" type="string" indexed="true" stored="true"/>
	<field name="mergerName" type="ik_word" />
	...

测试

请添加图片描述


springboot 集成

ElasticSearch

第一步:引入maven包

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

第二步:配置客户端对象

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

第三步:使用客户对象进行操作

官方api文档

package com.southsmart.demo.elasticsearch.controller;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.json.JSON;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.southsmart.demo.elasticsearch.config.ElasticSearchConfig;
import com.southsmart.demo.elasticsearch.mapper.CityMapper;
import com.southsmart.demo.elasticsearch.model.dto.CityDTO;
import com.southsmart.demo.elasticsearch.model.po.CityPO;
import com.southsmart.web.common.result.Result;
import lombok.RequiredArgsConstructor;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
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.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.client.indices.CreateIndexResponse;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.*;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.web.bind.annotation.*;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @author clm
 * @version 1.0
 * @since 2021/9/8
 */
@RestController
@RequestMapping("cityEs")
@RequiredArgsConstructor
public class CityEsController {
    @Autowired
    private RestHighLevelClient restHighLevelClient;

    @Autowired
    private CityMapper cityMapper;

    /**
     * 添加数据
     * @param indexName
     * @return
     * @throws IOException
     */
    @GetMapping("addCityData/{indexName}")
    public Result addCityData(@PathVariable String indexName) throws IOException {
        List<CityPO> cityList= cityMapper.selectList(new LambdaQueryWrapper<>());
        BulkRequest bulkRequest=new BulkRequest();
        bulkRequest.timeout(TimeValue.timeValueSeconds(10));
        for (int i = 0; i < cityList.size(); i++) {
            CityDTO dto= BeanUtil.copyProperties(cityList.get(i),CityDTO.class);

            //批量更新和批量删除在这里修改对应的请求即可
            bulkRequest.add(new IndexRequest(indexName)
                    .id(dto.getId()+"")
                    .source(JSONUtil.toJsonStr(dto),XContentType.JSON));
        }
        BulkResponse bulkResponse = restHighLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT);
        return Result.ok("插入成功");
    }

    /**
     * 查询
     * @param indexName
     * @param name
     * @param filedName
     * @param size
     * @return
     * @throws IOException
     */
    @GetMapping("search")
    public Result search(@RequestParam String indexName, @RequestParam String name, @RequestParam String filedName, @RequestParam Integer size) throws IOException {
        SearchRequest searchRequest = new SearchRequest(indexName);
        //构建搜索的条件
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        //QueryBuilders.termQuery() 精确匹配
        MultiMatchQueryBuilder termQueryBuilder = QueryBuilders.multiMatchQuery(name,filedName);
        //QueryBuilders.matchAllQuery();
        TermQueryBuilder termQueryBuilder1=QueryBuilders.termQuery(filedName,name);
        sourceBuilder.query(termQueryBuilder1);
        //分页 默认有 可以不写
        sourceBuilder.from(0);
        sourceBuilder.size(size);

        sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
        //构建搜索
        searchRequest.source(sourceBuilder);
        SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        SearchHits searchHits = searchResponse.getHits();
        List<Map<String, Object>> resultList=new ArrayList<>();
        for (SearchHit documentFields : searchResponse.getHits().getHits()) {
            resultList.add(documentFields.getSourceAsMap());
        }
        return Result.ok(resultList);
    }
}


Solr

第一步:引入maven包

因为maven仓库里面没有该jar包 从外部引用(在工程目录创建lib,将jar包放入其中)

请添加图片描述

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-data-solr</artifactId>
  <version>2.4.9</version>
  <systemPath>${project.basedir}/lib/spring-boot-starter-data-solr-2.4.9.jar</systemPath>
</dependency>

第二步:配置客户端

在application.properties中配置solr地址

spring.data.solr.host=http://localhost:8983/solr/demo-core

然后在项目中直接引入即可

@Autowired
private SolrClient solrClient;

第三步:使用客户对象进行操作

8.9官网api


package com.southsmart.demo.solr.controller;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.southsmart.demo.solr.mapper.CityMapper;
import com.southsmart.demo.solr.model.dto.CityDTO;
import com.southsmart.demo.solr.model.po.CityPO;
import com.southsmart.web.common.result.Result;
import lombok.RequiredArgsConstructor;
import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.SolrInputDocument;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.awt.print.Book;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author clm
 * @version 1.0
 * @since 2021/9/7
 */
@RestController
@RequestMapping("citySolr")
@RequiredArgsConstructor
public class CitySolrController {
    @Autowired
    private SolrClient solrClient;

    @Autowired
    private CityMapper cityMapper;

    /**
     * 刪除或者修改
     * @return
     */
    @PostMapping("addCity")
    public Result add() {
        try {
            List<CityPO> poList=cityMapper.selectList(new QueryWrapper<>());
            List<CityDTO> dtoList=new ArrayList<>();
            for (CityPO cityPO:poList){
                CityDTO cityDTO= BeanUtil.copyProperties(cityPO,CityDTO.class);
                dtoList.add(cityDTO);
            }
            solrClient.addBeans(dtoList);

            solrClient.commit();
        } catch (SolrServerException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return Result.ok();
    }

    /**
     * 根据id查询
     * @param id
     * @return
     * @throws IOException
     * @throws SolrServerException
     */
    @GetMapping("get/{id}")
    public Result get(@PathVariable String id) throws IOException, SolrServerException {
        SolrDocument solrDocument = solrClient.getById(id);
        System.out.println(solrDocument.getFieldNames());
        return Result.ok(solrDocument);
    }


    /**
     * 根据id删除
     * @return
     * @throws IOException
     * @throws SolrServerException
     */
    @GetMapping("delete")
    public Result delete() throws IOException, SolrServerException {
        List<CityPO> poList=cityMapper.selectList(new QueryWrapper<>());
        List<String> ids=poList.stream().map(m->m.getId()).collect(Collectors.toList());
        solrClient.deleteById(ids);
        solrClient.commit();
        return Result.ok();
    }

    /**
     * 查询
     * @param fieldName
     * @param mergerName
     * @param rows
     * @param startRow
     * @return
     * @throws IOException
     * @throws SolrServerException
     */
    @GetMapping("search")
    public Result search(@RequestParam String fieldName ,@RequestParam String mergerName,Integer rows,Integer startRow) throws IOException, SolrServerException {
        SolrQuery solrQuery  = new SolrQuery();
        //solrQuery.setQuery("mergerName:"+mergerName+" or name:"+mergerName);
        solrQuery.setQuery(fieldName+":"+mergerName);
        solrQuery.setRows(rows);
        solrQuery.setStart(startRow);

//        solrQuery.addHighlightField("mergerName");
//        //设置高亮的样式
//        solrQuery.setHighlightSimplePre("<font color='red'>");
//        solrQuery.setHighlightSimplePost("</font>");
//        System.out.println(solrQuery);
        QueryResponse response = solrClient.query(solrQuery);
        return Result.ok(response.getResults());
    }
}


对比

上手难度

1、Solr和Es安装及配置基本都差不多 开箱即用

2、新增、查询等操作也类似

综上 上手难度差不多

性能

请添加图片描述
请添加图片描述

请添加图片描述
请添加图片描述

当单纯的对已有数据进行搜索时,Solr更快。

当实时建立索引时, Solr会产生io阻塞,查询性能较差, Elasticsearch具有明显的优势。

随着数据量的增加,Solr的搜索效率会变得更低,而Elasticsearch却没有明显的变化。

综上所述,Solr的架构不适合实时搜索的应用。


流行度

Es是当今的主流

Es与Solr选型对比文章

Es与Solr选型对比视频

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值