Es的基本安装与配置参考我这篇文章 SpringBoot集成Elasticsearch(一)
本文使用kotlin来解释说明,其他语言可对照修改代码
代码实现:
@Document(indexName = "brand_es", type = "brand_es")
open class EsBrand {
@org.springframework.data.annotation.Id
@Field(type = FieldType.Keyword)
var brandID: String? = null
@Field(type = FieldType.Text,analyzer = "pinyin_analyzer",searchAnalyzer = "pinyin_analyzer",fielddata = true)
var brandCname: String? = null
@Field(type = FieldType.Text)
var brandName: String? = null
@Field(type = FieldType.Keyword)
var brandLogo: String? = null
}
注解说明:
@Document注解标明实体是Elasticsearch的Document,放在类上
public @interface Document {
String indexName();//索引库的名称,只能小写,不要用特殊字符,不能超过255字节
String type() default "";//索引库的类型,建议以实体的名称命名
boolean useServerConfiguration() default false;
short shards() default 5;//默认分区数
short replicas() default 1; //每个分区默认的备份数
String refreshInterval() default "1s";//索引文件存储类型
String indexStoreType() default "fs";
boolean createIndex() default true;
VersionType versionType() default VersionType.EXTERNAL;
}
@Field注解标明了字段的配置
public @interface Field {
@AliasFor("name")
String value() default ""; //默认值
@AliasFor("value")
String name() default "";//存在es的属性名,默认为定义的实体名
FieldType type() default FieldType.Auto;//自动检测属性的类型,可以根据实际情况自己设置
注:整体单词使用keyword,文本使用text
boolean index() default true;//默认情况下分词
DateFormat format() default DateFormat.none;//时间类型的格式化
String pattern() default "";
boolean store() default false;//默认情况下不存储原文
boolean fielddata() default false;//是否排序优化
String searchAnalyzer() default "";//指定字段被搜索时使用的分词器
String analyzer() default "";//指定字段建立索引分词时指定的分词器
String normalizer() default "";
String[] ignoreFields() default {};//忽略某个字段
boolean includeInParent() default false;
String[] copyTo() default {};
}
open interface BrandRepository : ElasticsearchRepository<EsBrand, String> {
fun findByBrandCname(brandCname: String): List<EsBrand>
fun deleteByBrandID(brandId: String)
fun findByBrandID(brandId: String): Optional<EsBrand>
}
定义一个接口继承ElasticsearchRepository,第一个参数为实体类,第二个参数为主键属性
在resources下创建elasticsearch_setting.json 文件
{
"index": {
"analysis": {
"analyzer": {
"pinyin_analyzer": {
"type": "custom",
"tokenizer": "ik_smart",//使用的分词器
"filter": ["my_pinyin", "word_delimiter"]//分词器过滤
}
},
"filter": {
"my_pinyin": {
"type": "pinyin",//你的插件的文件夹的名字
"keep_first_letter": true,//true:支持首字母
"keep_separate_first_letter": true,//支持首字母分隔
"keep_full_pinyin": true,//true:支持全拼
"keep_original": true,
"limit_first_letter_length": 16, //设置最大长度
"lowercase": true, //小写非中文字母
"remove_duplicated_term": true //重复的项将被删除
}
}
}
}
}
然后在实体类添加注解
@Setting(settingPath = "elasticsearch_setting.json")//设置setting
@Document(indexName = "brand_es", type = "brand_es")
open class EsBrand
在resources下创建elasticsearch_mapping.json 文件
注意:这里可以不需要mapping文件,定义mapping文件后实体类上字段的注解会失效
{
"properties": {
"uname": {
"type": "text",
"analyzer": "pinyin_analyzer",
"search_analyzer": "pinyin_analyzer"
},
"age": {
"type": "integer"
}
}
}
//引用mapping
@Mapping(mappingPath = "elasticsearch_mapping.json")//设置mapping
@NoRepositoryBean
public interface ElasticsearchRepository<T, ID extends Serializable> extends ElasticsearchCrudRepository<T, ID> {
<S extends T> S index(S var1);
Iterable<T> search(QueryBuilder var1);
Page<T> search(QueryBuilder var1, Pageable var2);
Page<T> search(SearchQuery var1);
Page<T> searchSimilar(T var1, String[] var2, Pageable var3);
void refresh();
Class<T> getEntityClass();
}
实际使用中,是通过构建NativeSearchQuery来完成一些复杂的查询的。
说明参考:ElasticSearchRepository的基本使用
QueryBuilder 的几个方法 QueryBuilder 的使用
//按自己设置的分词器搜索
QueryBuilders.matchQuery("brandCname",keyword)
//精确查询 完全匹配
QueryBuilders.termQuery("groupId",request.groupId)
//模糊匹配,以*为匹配符
QueryBuilders.wildcardQuery("brandName", "*$keyword*")
//组合查询,前面必须是QueryBuilders.boolQuery(),should代表or,must代表and
QueryBuilders.boolQuery().should(QueryBuilders.matchQuery("brandCname",keyword))
.must(QueryBuilders.wildcardQuery("brandName", "*$keyword*"))
//QueryBuilders是可以单独使用的
val esBrands = repository.search(query)
有时候需要自己排序,这时就要用到SortBuilder
SortBuilders.fieldSort("字段属性名").order(SortOrder.ASC);//字段排序
注意:要排序的字段必须添加 fielddata = true 的设置,否则会报错
分页查询
//通过PageRequest构建分页
val page = PageRequest.of(0, 2) //第一个参数是页码,第二个参数为每页返回条数,es的分页是从0开始的
val esBrands = repository.search(query,page)
有的人可能说了,我全都要怎么办,那就要用到下面的方法
NativeSearchQueryBuilder的构建
//聚合查询NativeSearchQueryBuilder的使用
var fsb = SortBuilders.fieldSort("brandCname").order(SortOrder.ASC);
var bqb = QueryBuilders.boolQuery().should(QueryBuilders.matchQuery("brandCname",keyword))
.should(QueryBuilders.wildcardQuery("brandName", "*$keyword*"))
var query = NativeSearchQueryBuilder()
.withQuery(bqb)
.withSort(fsb)
.withPageable(pageable)
.build();
//完整示例
open class EsBrandService {
@Autowired
private lateinit var repository: BrandRepository
fun fetchPageBrandsByKeyWord(keyword :String,pageable :PageRequest): List<EsBrand> {
var fsb = SortBuilders.fieldSort("brandCname").order(SortOrder.ASC);
var bqb = QueryBuilders.boolQuery().should(QueryBuilders.matchQuery("brandCname",keyword)).should(QueryBuilders.wildcardQuery("brandName", "*$keyword*"))
var query = NativeSearchQueryBuilder()
.withQuery(bqb)
.withSort(fsb)
.withPageable(pageable)
.build();
val esBrands = repository.search(query)
val brands = Lists.newArrayList(esBrands)
return brands
}
}
至此,已经满足了es的基本使用,一般线上服务器都是linux系统,这里可能需要配置es服务开机自启,
可以参考这篇文章 Elasticsearch 在CentOs7 环境中开机启动
最后欢迎大家指出这篇文章的不足,共同进步!!!