SpringData自定义查询
SpringData框架提供的基本增删改查方法并不能完全满足我们的业务需要
如果是针对当前Es数据,进行个性化的自定义查询,那还是需要自己编写查询代码
就像我们要实现根据关键词查询商品信息一样,完成类似数据库中的模糊查询.
单条件查询
我们使用SpringDataES进行查询,本质上还是相当于ES文档中执行的查询语句
在SpringData框架下,ItemRepository接口中实现更加简单
// SpringData自定义查询
// 我们要编写一个遵循SpringData给定的方法名的格式
// SpringData能够根据我们编写的方法名,推断出查询意图,自动生成能够完成这个查询的语句完成功能
// query(查询):表达当前方法是一个查询方法,类似数据库sql语句的select
// Item/Items:是要查询的实体类的名称,返回集合的查询应该以s结尾
// By(通过/根据):标识开始设置查询条件的关键字,等价于sql语句中的where
// Title:要查询的字段,可以是Item实体类中的任何字段
// Matches(匹配):指定查询的操作条件,Matches是查询匹配关键词的行(document),类似于sql中的like
Iterable<Item> queryItemsByTitleMatches(String title);
下面可以开始在测试类中进行测试查询
// 单条件自定义查询
@Test
void queryOne(){
// 查询items索引中,title字段包含"游戏"分词的数据
Iterable<Item> items=itemRepository.queryItemsByTitleMatches("游戏");
items.forEach(item -> System.out.println(item));
}
上面代码运行时底层运行的查询语句为:
### 单条件搜索
POST http://localhost:9200/items/_search
Content-Type: application/json
{
"query": {"match": { "title": "游戏" }}
}
多条件查询
在相对复杂的查询逻辑下
经常使用多个条件来定位查询需要的数据
这样就需要逻辑运算符"and"/"or"
ItemRepository接口中添加多条件的查询方法
// 多条件自定义查询
// 多个条件之间要使用and或or进行分隔,表示多个条件之间的逻辑关系
// 我们使用title和brand字段进行多条件查询
// 参数的数量要匹配查询字段的数量
// 声明参数的顺序就是赋值的依据,第一个参数会赋值给第一个条件,和参数名称无关
Iterable<Item> queryItemsByTitleMatchesAndBrandMatches(String title,String brand);
测试代码如下
// 多条件自定义查询
@Test
void queryTwo(){
// 查询title字段是"游戏",并且品牌是"罗技"的数据
Iterable<Item> items=itemRepository
.queryItemsByTitleMatchesAndBrandMatches("游戏","罗技");
items.forEach(item -> System.out.println(item));
}
底层运行的请求
### 多字段搜索
POST http://localhost:9200/items/_search
Content-Type: application/json
{
"query": {
"bool": {
"must": [
{ "match": { "title": "游戏"}},
{ "match": { "brand": "罗技"}}
]
}
}
}
当查询条件关系为and时,查询语句关键字为must
当查询条件关系为or时,查询语句关键字为should
排序查询
默认情况下从ES中查询获得的数据排序依据是ES查询得出的相关性分数(score)
但是如果想改变这个排序就需要在查询方法上添加新的关键字
在ItemRepository接口添加具备排序功能的查询方法测试代码如下
// 排序查询
Iterable<Item> queryItemsByTitleMatchesOrBrandMatchesOrderByPriceDesc(
String title,String brand);
测试代码如下
// 排序查询
@Test
void queryOrder(){
// 查询title字段是"游戏",或品牌是"罗技"的数据,用价格降序排序显示
Iterable<Item> items=itemRepository
.queryItemsByTitleMatchesOrBrandMatchesOrderByPriceDesc(
"游戏","罗技");
items.forEach(item -> System.out.println(item));
}
底层运行的代码
### 多字段搜索
POST http://localhost:9200/items/_search
Content-Type: application/json
{
"query": {
"bool": {
"should": [
{ "match": { "title": "游戏"}},
{ "match": { "brand": "罗技"}}
]
}
},"sort":[{"price":"desc"}]
}
分页查询
SpringData框架支持完成分页查询
需要在ItemRepository接口中修改方法的参数和返回值就可以实现
//分页查询
//要执行分页查询, 需要返回值类型修改为Page
//这个类型对象支持保存所有查询结果的同时,保存分页信息,例如每页条数、当前页、总页数、总条数等
//参数方面,要有现有所有参数最后一个Pageable类型的参数
//这个参数会在方法被调用时,确定分页查询的页码和每页条数
Page<Item> queryItemByTitleMathesOrBrandMatchesOrderByPriceDesc(String title,String brand,Pageable pageable) ;
测试代码
// 分页查询
@Test
void queryPage(){
int page=1; // 要查询的页码
int pageSize=2; // 设置每页的条数
Page<Item> pageItems=itemRepository
.queryItemsByTitleMatchesOrBrandMatchesOrderByPriceDesc(
"游戏","罗技", PageRequest.of(page-1,pageSize));
pageItems.forEach(item -> System.out.println(item));
// pageItems对象包含的分页信息输出如下
System.out.println("总页数:"+pageItems.getTotalPages());
System.out.println("总条数:"+pageItems.getTotalElements());
System.out.println("当前页:"+(pageItems.getNumber()+1));
System.out.println("每页条数:"+pageItems.getSize());
System.out.println("是否是首页:"+pageItems.isFirst());
System.out.println("是否是末页:"+pageItems.isLast());
}