跳至主要內容

ElasticSearch 全文搜索工具使用手册

大约 8 分钟

ElasticSearch 全文搜索工具使用手册

1. 快速使用

使用前说明

组件基于JDK1.8编译,请注意JDK版本的选择 目前只支持springboot方式集成,如果需要与普通spring系统集成需要做简单改造。如果您并不需要使用组件自带的集成方式,仅需参考与es集成的方式请注意关注ElasticsearchTemplateImpl类中的代码即可

  1. 引用依赖包

    在pom.xml文件中引入

        <dependency>
            <groupId>com.pcitc.si</groupId>
            <artifactId>common-search-starter</artifactId>
            <version>1.0.0-SNAPSHOT</version>
        </dependency>
    

    特别注意:建议在引入的springboot工程中pom文件添加elasticsearch版本号,否则可能被springboot parent工程覆盖。

    <properties>
        ……
        <elasticsearch.version>7.15.2</elasticsearch.version>
        ……
    </properties>
    
  2. 引入组件

    在启动类上增加 @EnableESTools 注解。

    该注解能够帮助开发人员自动注入工具服务,简化配置,并引入自动发现es索引结构实体类的功能,识别ESCRepository接口并自动生成代理的功能。

    @EnableESTools
    @SpringBootApplication
    @ComponentScan
    public class AuthServerApp {
        public static void main(String[] args) {
            SpringApplication.run(AuthServerApp.class, args);
            System.out.println("启动成功");
        }
    }
    

    使用 EnableESTools 注解时,也可以指定需要扫描的索引接口包路径和索引结构实体包路径。

    @EnableESTools({"实体类包路径数组"})
    或
    @EnableESTools(
    basePackages = {"ESCRepository接口包路径数组"},entityPath = {"实体类包路径数组"})   
    
  3. 参数配置

    一、elasticsearch服务的uri配置(必须配置)

    application.properties添加elasticsearch服务的uri,如果有多个(集群情况)请用半角逗号,隔开。

    elasticsearch.host=127.0.0.1:9200
    

    二、elasticsearch httpclient的连接池参数配置(必须配置)

     #连接池里的最大连接数
     elasticsearch.max_connect_total=30
     #某一个/每服务每次能并行接收的请求数量
     elasticsearch.max_connect_per_route=10
     #http clilent中从connetcion pool中获得一个connection的超时时间
     elasticsearch.connection_request_timeout_millis=2000
     #响应超时时间,超过此时间不再读取响应
     elasticsearch.socket_timeout_millis=30000
     #链接建立的超时时间
     elasticsearch.connect_timeout_millis=2000
    

    三、elasticsearch用户名密码配置(可选配置)

     没有可以不配
     elasticsearch.username=elastic
     elasticsearch.password=changeme
    
  4. 常规使用

    在spring管理的bean内直接自动注入组件内置的两个工具服务:ElasticsearchTemplate、ElasticsearchIndex并调用相关api即可。

    @Autowired
    private ElasticsearchTemplate elasticsearchTemplate;
    
    @RequestMapping("es_search")
    public PageList<Article> esSearch(@RequestBody Map vo) throws Exception{
    
        //定制分页信息
        int currentPage = 1;
        int pageSize = 10;
        //分页
        PageSortHighLight psh = new PageSortHighLight(currentPage,pageSize);
        //排序字段,注意如果proposal_no是text类型会默认带有keyword性质,需要拼接.keyword
        // String sorter = "index_uuid";
        // Sort.Order order = new Sort.Order(SortOrder.ASC,sorter);
        // psh.setSort(new Sort(order));
        //定制高亮,如果定制了高亮,返回结果会自动替换字段值为高亮内容
        HighLight highLight = new HighLight();
        highLight.setPreTag("<em>");
        highLight.setPostTag("</em>");
        psh.setHighLight(highLight.field("content"));
    
        PageList<Article> pageList = new PageList<>();
        PageSortHighLight psh1 = new PageSortHighLight(1, 50);
        psh1.setHighLight(highLight);
        Attach attach = new Attach();
        attach.setPageSortHighLight(psh1);
        pageList = elasticsearchTemplate.search(QueryBuilders.fuzzyQuery("content", vo.get("content")), attach, Article.class);
        pageList.getList().forEach(s -> System.out.println(s));
        return pageList;
    }
    
  5. 接口代理方式使用推荐

    采用接口代理的方式,可以快速实现一些基础功能。

    步骤:

    一、定义索引对应的实体类

    实体需要加上 ESMetaData 的注解,以标识出索引的名称等属性,实体字段通过 ESID 标识id,通过 ESMapping 注解标识出字段的类型,还可指定分词器类型,标识keyword等。

    相关注解详细说明参考:索引实体注解说明

    项目启动时,组件会自动识别es实体类上配置的@ESMetaData注解,如果对应的索引结构没有创建,自动根据mapping注解配置创建相关索引结构。

    如果实体类不在启动类的包路径下,如需启用此功能,需要在启动注解上配置实体类路径。

    @EnableESTools(entityPath = "com.*.esdemo.domain")
    

    示例:

     @Data
     @ESMetaData(indexName = "article",autoCreateIndex = true)
     public class Article implements Serializable{
         @ESID
         private String id;
    
         @ESMapping(datatype = DataType.text_type)
         private String title;
    
         @ESMapping(datatype = DataType.text_type,analyzer = Analyzer.ik_smart,search_analyzer = Analyzer.ik_smart)
         private String content;
    
         @ESMapping(datatype = DataType.date_type)
         private Date createTime;
     }
    

    二、定义自动代理接口类

    接口类只需要继承ESCRepository接口即可。示例如下:

    public interface ArticleRepository extends ESCRepository<Article,String> {
    
    }
    

    三、使用

    使用方法与ElasticsearchTemplate大同小异,只有一些比较基础的方法,去掉了Clazz类类型的入参

    Article article = new Article();
    article.setId("111111");
    article.setTitle("文章标题");
    article.setContent("文章内容!!!");
    articleRepository.save(main2);
    System.out.println(main2Repository.getById("111111"));
    
    Map map2 = articleRepository.aggs("id", AggsType.count,null,"title");
    map2.forEach((o, o2) -> System.out.println(o + "=====" + o2));
    

    注意事项: 如果采用自动代理接口的方式,需要注意以下几点:

    接口必须继承自ESCRepository,并且定义接口时必须注明泛型的真实类型 对应的实体类必须添加ESMetaData注解,组件才能自动识别 实体类名称整个工程内不能重复,否则会导致生成代理类失败

2. 索引实体注解说明

2.1 @ESMetaData

ESMetaData 注解主要用于配置索引的基本信息。

用法:

@ESMetaData(indexName = "index", number_of_shards = 5,number_of_replicas = 0)

具体信息如下:

/**
 * 检索时的索引名称,如果不配置则默认为和indexName一致,该注解项仅支持搜索
 * 并不建议这么做,建议通过特定方法来做跨索引查询
 */
String[] searchIndexNames() default {};
/**
 * 索引名称,必须配置
 */
String indexName();
/**
 * 索引类型,可以不配置,不配置默认为_doc,墙裂建议每个index下只有一个type
 */
String indexType() default "";
/**
 * 主分片数量
 */
int number_of_shards() default 5;
/**
 * 备份分片数量
 */
int number_of_replicas() default 1;
/**
 * 是否打印日志
 * @return
 */
boolean printLog() default false;
/**
 * 别名、如果配置了后续增删改查都基于这个alias
 * 当配置了此项后自动创建索引功能将失效
 * indexName为aliasName
 * @return
 */
 boolean alias() default false;

/**
* 别名对应的索引名称
* 当前配置仅生效于配置了alias但没有配置rollover
* 注意:所有配置的index必须存在
* @return
*/
String[] aliasIndex() default {};

/**
* 当配置了alias后,指定哪个index为writeIndex
* 当前配置仅生效于配置了alias但没有配置rollover
* 注意:配置的index必须存在切在aliasIndex中
* @return
*/
String writeIndex() default "";

/**
* 当配置了rollover为true时,开启rollover功能(并忽略其他alias的配置)
* aliasName为indexName
* 索引名字规格为:indexName-yyyy.mm.dd-00000n
* 索引滚动生成策略如下
* @return
*/
boolean rollover() default false;

 /**
 * 自动执行rollover相关配置
 * 自动执行rollover开关
 * @return
 */
 boolean autoRollover() default false;

/**
* 自动执行rollover相关配置
* 项目启动后延迟autoRolloverInitialDelay时间后开始执行
* @return
*/
long autoRolloverInitialDelay() default 0L;

/**
* 自动执行rollover相关配置
* 项目启动后每间隔autoRolloverPeriod执行一次
* @return
*/
long autoRolloverPeriod() default 4L;

/**
* 自动执行rollover相关配置
* 单位时间配置,与autoRolloverPeriod、autoRolloverInitialDelay对应
* @return
*/
TimeUnit  autoRolloverTimeUnit() default TimeUnit.HOURS;


/**
* 当前索引超过此项配置的时间后生成新的索引
* @return
*/
long rolloverMaxIndexAgeCondition() default 0L;

/**
* 与rolloverMaxIndexAgeCondition联合使用,对应rolloverMaxIndexAgeCondition的单位
* @return
*/
TimeUnit rolloverMaxIndexAgeTimeUnit() default TimeUnit.DAYS;

/**
* 当前索引文档数量超过此项配置的数字后生成新的索引
* @return
*/
long rolloverMaxIndexDocsCondition() default 0L;

/**
* 当前索引大小超过此项配置的数字后生成新的索引
* @return
*/
long rolloverMaxIndexSizeCondition() default 0L;

/**
* 与rolloverMaxIndexSizeCondition联合使用,对应rolloverMaxIndexSizeCondition的单位
* @return
*/
ByteSizeUnit rolloverMaxIndexSizeByteSizeUnit() default ByteSizeUnit.GB;

/**
* 最大分页深度
* @return
*/
long maxResultWindow() default 10000L;

/**
* 索引名称是否自动包含后缀
* @return
*/
boolean suffix() default false;

/**
* 是否自动创建索引
* @return
*/
boolean autoCreateIndex() default true;

2.2 索引结构字段配置注解

用于定制es索引结构对应实体类的索引结构,以简化创建索引工作。将相关注解配置于实体类field上,用于标识field对应elasticsearch索引结构字段的相关信息。

主要和 @ESID 和 @ESMapping 这2个注解。

@ESID
private String proposal_no;
@ESMapping(datatype = DataType.keyword_type)
private String risk_code;
@ESMapping(datatype = DataType.text_type)
private String risk_name;

@ESID注解: 标识es主键(自动对应es索引数据_id字段),注意:主键的类型需要与ElasticsearchTemplate的第二泛型一致。

@ESMapping: 标识字段对应es索引结构字段的相关信息。

ESMapping配置项:

/**
 * 数据类型(包含 关键字类型)
 */
DataType datatype() default DataType.text_type;
/**
 * 间接关键字
 */
boolean keyword() default true;
/**
 * 关键字忽略字数
 */
int ignore_above() default 256;
/**
 * 是否支持ngram,高效全文搜索提示(定制gram分词器,请参照官方例https://www.elastic.co/guide/en/elasticsearch/reference/7.x/analysis-ngram-tokenizer.html)
 */
boolean ngram() default false;
/**
 * 是否支持suggest,高效前缀搜索提示
 */
boolean suggest() default false;
/**
 * 索引分词器设置(研究类型)
 */
Analyzer analyzer() default Analyzer.standard;
/**
 * 搜索内容分词器设置
 */
Analyzer search_analyzer() default Analyzer.standard;
/**
 * 是否允许被搜索
 */
boolean allow_search() default true;

/**
 * 拷贝到哪个字段,代替_all
 */
String copy_to() default "";

/**
* null_value指定,默认空字符串不会为mapping添加null_value
* 对于值是null的进行处理,当值为null是按照注解指定的‘null_value’值进行查询可以查到
* 需要注意的是要与根本没有某字段区分(没有某字段需要用Exists Query进行查询)
* 建议设置值为NULL_VALUE
* @return
*/
String null_value() default "";

/**
* nested对应的类型,默认为Object.Class。
* 对于DataType是nested_type的类型才需要添加的注解,通过这个注解生成嵌套类型的索引
* 例如:
* @ESMapping(datatype = DataType.nested_type, nested_class = EsFundDto.class)
*
* @return
*/
Class nested_class() default Object.class;