一、实体类索引注解说明:
@Document(indexName = "user_db", type = "user_table")
public class User{
@Id
@Field(type = FieldType.Keyword)
private String userId;
@Field(type= FieldType.Keyword)
private String account;
@Field(type= FieldType.Keyword)
private String userName;
@Field(type= FieldType.Keyword)
private String idCard;
@Field(type = FieldType.Date,
format = DateFormat.custom,
pattern = "yyyy-MM-dd HH:mm:ss")
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
//DOTO
//get和set方法
//toString()方法
}
1、@Document注解作用在类上,标记实体类为文档对象,常用属性如下:
- (1)indexName:对应索引库名称,相当于数据库名称;
- (2)type:对应在索引库中的类型,相当于表名称;
- (3)shards:分片数
- (4)replicas:副本数.
2、@Field作用在成员变量,标记为文档的字段,并制定映射属性;
- (1)@Id:作用在成员变量,标记一个字段为id主键;一般id字段或是域,不需要存储也不需要分词,用于hash后进行分片;类型必须为字符串
- (2)type:字段的类型,取值是枚举,FieldType;
- (3)index:是否索引,布尔值类型,默认是true;
- (4)store:是否存储,布尔值类型,默认值是false;
- (5)analyzer:分词器名称
- 【@Field(type = FieldType.Keyword)和 @Field(type = FieldType.Text)区别】
- FieldType.Keyword存储字符串数据时,不会建立索引;而FieldType.Text在存储字符串数据的时候,会自动建立索引,也会占用部分空间资源。
- 【@Field(store = true)】
- 其实不管我们将store值设置为true或false,elasticsearch都会将该字段存储到Field域中;但是他们的区别是什么?
- (1)store = false时,默认设置;那么给字段只存储在"_source"的Field域中;
- (2)store = true时,该字段的value会存储在一个跟_source平级的独立Field域中;同时也会存储在_source中,所以有两份拷贝。
- 那么我们在什么样的业务场景下使用store field功能?
- (1)_source field在索引的mapping 中disable了。这种情况下,如果不将某个field定义成store=true,那些将无法在返回的查询结果中看到这个field。
- (2)_source的内容非常大。这时候如果我们想要在返回的_source document中解释出某个field的值的话,开销会很大(当然你也可以定义source filtering将减少network overhead), 比例某个document中保存的是一本书,所以document中可能有这些field: title, date, content。假如我们只是想查询书的title 跟date信息,而不需要解释整个_source(非常大), 这个时候我们可以考虑将title, date这些field设置成store=true。需要注意的是,看起来将field store可以减少查询的开销,但其实这样也会加大disk的访问频率。假如你将_source中的10个field都定义store,那么在你查询这些field的时候会将会有10次disk seek的操作。而返回_source只有一次disk seek的操作。所以这个也是我们在定义的时候需要blance的。
二、Repository使用说明
package com.myelastic.repository;
import com.myelastic.model.User;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
public interface UserRepository extends ElasticsearchRepository<User, String> {
User findByUserId(StringuserId);
@Query("{"bool" : {"must" : {"field" : {"userName" : "?0"}}}}")
Page<User > findByUserName(String userName,Pageable pageable);
}
1、通过方法名称查询:
Repository提供两个基础父类供用户使用,分别是ElasticsearchRepository<T, ID extends Serializable>和ElasticsearchCrudRepository<T, ID extends Serializable>,其中ElasticsearchRepository继承了ElasticsearchCrudRepository,添加了一些查询方法,如Iterable search(QueryBuilder var1);Page search(QueryBuilder var1, Pageable var2);等,用户自定义的Repository可以继承这两个类,其中T指索引实体类,ID指索引主键Id类型,如以上用户自定义的UserRepository.java。用户还可以在自定义的Repository里根据业务需要自行方法定义,如findByUserNameAndIdCard 根据名字和身份证查询符合条件的记录,and表示逻辑与,UserName和IdCard表示用户属性。常见规则如下:
2、通过@Query注解查询:
@Query("{“bool” : {“must” : {“field” : {“userName” : “?0”}}}}")
Page findByUserName(String userName,Pageable pageable);
bool表示布尔查询,must表示必须,field为需要查询的属性名称集合,?为占位符,代替参数。
3、过滤查询,查询性能更好
/**
* must 多条件 &(并且)
* mustNot 多条件 != (非)
* should 多条件 || (或)
*/
QueryBuilder query = QueryBuilders.boolQuery()
.must(QueryBuilders.termQuery("userId","2019040499")) //精确查询
.must(QueryBuilders.wildcardQuery("userName","*华腾")) //模糊查询
.must(QueryBuilders.rangeQuery("createDate")
.from(DateUtil.getDateTimeString())
.to(DateUtil.getDateTimeString())); //范围查询
List<String> properties = new ArrayList<>();
Sort sort = Sort.by(Sort.Direction.DESC,"createDate");//排序
//多条件排序
/*Sort.Order order1 = new Sort.Order(Sort.Direction.DESC,"userId");
Sort.Order order2 = new Sort.Order(Sort.Direction.ASC,"userId");
Sort sortList = Sort.by(order1,order2);*/
Pageable pageable = PageRequest.of(0, 10, sort);
Page<User> userPage = userReposity.search(query, pageable);
List<User> pageContent= userPage.getContent();