最后
import com.itzheng.es.pojo.Item;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.test.context.junit4.SpringRunner;
/*
Springboot的@RunWith(SpringRunner.class)
注解的意义在于Test测试类要使用注入的类,比如@Autowired注入的类,
有了@RunWith(SpringRunner.class)这些类才能实例化到spring容器中,自动注入才能生效,
不然直接一个NullPointerExecption
*/
@RunWith(SpringRunner.class)
@SpringBootTest
public class EsTest {
@Autowired
ElasticsearchTemplate template;
@Test
public void testCreate(){
//创建索引库
template.createIndex(Item.class);//创建索引
//指定映射关系
template.putMapping(Item.class);
}
}
6、运行测试类
(1)运行测试
运行成功
(2)通过Kabina查看
GET itzhengitem
返回结果
{
“itzhengitem” : {
“aliases” : { },
“mappings” : {
“properties” : {
“brand” : {
“type” : “keyword”
},
“category” : {
“type” : “keyword”
},
“id” : {
“type” : “keyword”
},
“images” : {
“type” : “keyword”,
“index” : false
},
“price” : {
“type” : “double”
},
“title” : {
“type” : “text”,
“analyzer” : “ik_smart”
}
}
},
“settings” : {
“index” : {
“routing” : {
“allocation” : {
“include” : {
“_tier_preference” : “data_content”
}
}
},
“refresh_interval” : “1s”,
“number_of_shards” : “1”,
“provided_name” : “itzhengitem”,
“creation_date” : “1629355397115”,
“store” : {
“type” : “fs”
},
“number_of_replicas” : “1”,
“uuid” : “2cUsvBtgQ4uOARwTuQoHAA”,
“version” : {
“created” : “7140099”
}
}
}
}
}
只查看映射
GET itzhengitem/_mapping
{
“itzhengitem” : {
“mappings” : {
“properties” : {
“brand” : {
“type” : “keyword”
},
“category” : {
“type” : “keyword”
},
“id” : {
“type” : “keyword”
},
“images” : {
“type” : “keyword”,
“index” : false
},
“price” : {
“type” : “double”
},
“title” : {
“type” : “text”,
“analyzer” : “ik_smart”
}
}
}
}
}
1、编写测试方法
package com.itzheng.es.demo;
import com.itzheng.es.pojo.Item;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.test.context.junit4.SpringRunner;
/*
Springboot的@RunWith(SpringRunner.class)
注解的意义在于Test测试类要使用注入的类,比如@Autowired注入的类,
有了@RunWith(SpringRunner.class)这些类才能实例化到spring容器中,自动注入才能生效,
不然直接一个NullPointerExecption
*/
@RunWith(SpringRunner.class)
@SpringBootTest
public class EsTest {
@Autowired
ElasticsearchTemplate template;
@Test
public void testCreate(){
//创建索引库
template.createIndex(Item.class);//创建索引
//指定映射关系
template.putMapping(Item.class);
}
@Test
public void testDelete(){
template.deleteIndex(“itzhengitem”);
}
}
运行成功
2、通过Kabina查看
GET itzhengitem
返回结果
{
“error” : {
“root_cause” : [
{
“type” : “index_not_found_exception”,
“reason” : “no such index [itzhengitem]”,
“resource.type” : “index_or_alias”,
“resource.id” : “itzhengitem”,
“index_uuid” : “na”,
“index” : “itzhengitem”
}
],
“type” : “index_not_found_exception”,
“reason” : “no such index [itzhengitem]”,
“resource.type” : “index_or_alias”,
“resource.id” : “itzhengitem”,
“index_uuid” : “na”,
“index” : “itzhengitem”
},
“status” : 404
}
为了方便我们需要再次创建刚刚的索引
Spring Data 的强大之处,就在于你不用写任何DAO处理,自动根据方法名或类的信息进行CRUD操作。
只要你定义一个接口,然后继承Repository提供的一些子接口,就能具备各种基本的CRUD功能。
我们只需要定义接口,然后继承它就OK了。
定义一个接口
package com.itzheng.es.repository;
import com.itzheng.es.pojo.Item;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
public interface ItemRepository extends ElasticsearchRepository<Item,Long> {
//上述泛型的第一个参数的实体类类型,第二个是主键ID类型
}
1、新增文档
(1)首先注入
@Autowired
private ItemRepository repository;
(2)编写测试方法
@Test
public void insertIndex(){
Item item = new Item(1L, “小米手机7”, " 手机", “小米”, 3499.00, “http://image.leyou.com/13123.jpg”);
repository.save(item);
}
(3)运行测试方法
(4)通过Kabina查看
GET itzhengitem/_search
{
“took” : 0,
“timed_out” : false,
“_shards” : {
“total” : 1,
“successful” : 1,
“skipped” : 0,
“failed” : 0
},
“hits” : {
“total” : {
“value” : 1,
“relation” : “eq”
},
“max_score” : 1.0,
“hits” : [
{
“_index” : “itzhengitem”,
“_type” : “item”,
“_id” : “1”,
“_score” : 1.0,
“_source” : {
“id” : 1,
“title” : “小米手机7”,
“category” : " 手机",
“brand” : “小米”,
“price” : 3499.0,
“images” : “http://image.leyou.com/13123.jpg”
}
}
]
}
}
2、批量新增
@Test
public void indexList(){
List list = new ArrayList<>();
list.add(new Item(2L, “坚果手机R1”, " 手机", “锤子”, 3699.00, “http://image.leyou.com/123.jpg”));
list.add(new Item(3L, “华为META10”, " 手机", “华为”, 4499.00, “http://image.leyou.com/3.jpg”));
repository.saveAll(list);
}
运行测试
运行成功
通过Kabina查看
GET itzhengitem/_search
{
“took” : 0,
“timed_out” : false,
“_shards” : {
“total” : 1,
“successful” : 1,
“skipped” : 0,
“failed” : 0
},
“hits” : {
“total” : {
“value” : 3,
“relation” : “eq”
},
“max_score” : 1.0,
“hits” : [
{
“_index” : “itzhengitem”,
“_type” : “item”,
“_id” : “1”,
“_score” : 1.0,
“_source” : {
“id” : 1,
“title” : “小米手机7”,
“category” : " 手机",
“brand” : “小米”,
“price” : 3499.0,
“images” : “http://image.leyou.com/13123.jpg”
}
},
{
“_index” : “itzhengitem”,
“_type” : “item”,
“_id” : “2”,
“_score” : 1.0,
“_source” : {
“id” : 2,
“title” : “坚果手机R1”,
“category” : " 手机",
“brand” : “锤子”,
“price” : 3699.0,
“images” : “http://image.leyou.com/123.jpg”
}
},
{
“_index” : “itzhengitem”,
“_type” : “item”,
“_id” : “3”,
“_score” : 1.0,
“_source” : {
“id” : 3,
“title” : “华为META10”,
“category” : " 手机",
“brand” : “华为”,
“price” : 4499.0,
“images” : “http://image.leyou.com/3.jpg”
}
}
]
}
}
多新增几条数据
@Test
public void indexList(){
List list = new ArrayList<>();
list.add(new Item(4L, “小米手机7”, “手机”, “小米”, 3299.00, “http://image.leyou.com/13123.jpg”));
list.add(new Item(5L, “坚果手机R1”, “手机”, “锤子”, 3699.00, “http://image.leyou.com/13123.jpg”));
list.add(new Item(6L, “华为META10”, “手机”, “华为”, 4499.00, “http://image.leyou.com/13123.jpg”));
list.add(new Item(7L, “小米Mix2S”, “手机”, “小米”, 4299.00, “http://image.leyou.com/13123.jpg”));
list.add(new Item(8L, “荣耀V10”, “手机”, “华为”, 2799.00, “http://image.leyou.com/13123.jpg”));
repository.saveAll(list);
}
3、修改文档
修改和新增是同一个接口,区分的依据就是id
这一点跟我们在页面发起PUT请求是类似的。
修改id为1 的数据
@Test
public void updateIndex(){
Item item = new Item(1L, “大米手机7”, " 手机", “小米”, 3499.00, “http://image.leyou.com/13123.jpg”);
repository.save(item);
}
通过Kabina查看
GET itzhengitem/_search
4、基本查询
ElasticsearchRepository提供了一些基本的查询方法:
(1)通过id查询
@Test
public void testQuery(){
Optional optional = this.repository.findById(1L);
System.out.println(optional.get());
}
(2)查询所有
@Test
public void testFind(){
Iterable items = repository.findAll();
for (Item item : items) {
System.out.println(item);
}
}
运行结果
(3) 自定义方法
Spring Data 的另一个强大功能,是根据方法名称自动实现功能。
比如:你的方法名叫做:findByTitle,那么它就知道你是根据title查询,然后自动帮你完成,无需写实现类。
当然,方法名称要符合一定的约定:
| Keyword | Sample | Elasticsearch Query String |
| — | — | — |
| And
| findByNameAndPrice
| {"bool" : {"must" : [ {"field" : {"name" : "?"}}, {"field" : {"price" : "?"}} ]}}
|
| Or
| findByNameOrPrice
| {"bool" : {"should" : [ {"field" : {"name" : "?"}}, {"field" : {"price" : "?"}} ]}}
|
| Is
| findByName
| {"bool" : {"must" : {"field" : {"name" : "?"}}}}
|
| Not
| findByNameNot
| {"bool" : {"must_not" : {"field" : {"name" : "?"}}}}
|
| Between
| findByPriceBetween
| {"bool" : {"must" : {"range" : {"price" : {"from" : ?,"to" : ?,"include_lower" : true,"include_upper" : true}}}}}
|
| LessThanEqual
| findByPriceLessThan
| {"bool" : {"must" : {"range" : {"price" : {"from" : null,"to" : ?,"include_lower" : true,"include_upper" : true}}}}}
|
| GreaterThanEqual
| findByPriceGreaterThan
| {"bool" : {"must" : {"range" : {"price" : {"from" : ?,"to" : null,"include_lower" : true,"include_upper" : true}}}}}
|
| Before
| findByPriceBefore
| {"bool" : {"must" : {"range" : {"price" : {"from" : null,"to" : ?,"include_lower" : true,"include_upper" : true}}}}}
|
| After
| findByPriceAfter
| {"bool" : {"must" : {"range" : {"price" : {"from" : ?,"to" : null,"include_lower" : true,"include_upper" : true}}}}}
|
| Like
| findByNameLike
| {"bool" : {"must" : {"field" : {"name" : {"query" : "?*","analyze_wildcard" : true}}}}}
|
| StartingWith
| findByNameStartingWith
| {"bool" : {"must" : {"field" : {"name" : {"query" : "?*","analyze_wildcard" : true}}}}}
|
| EndingWith
| findByNameEndingWith
| {"bool" : {"must" : {"field" : {"name" : {"query" : "*?","analyze_wildcard" : true}}}}}
|
| Contains/Containing
| findByNameContaining
| {"bool" : {"must" : {"field" : {"name" : {"query" : "**?**","analyze_wildcard" : true}}}}}
|
| In
| findByNameIn(Collection<String>names)
| {"bool" : {"must" : {"bool" : {"should" : [ {"field" : {"name" : "?"}}, {"field" : {"name" : "?"}} ]}}}}
|
| NotIn
| findByNameNotIn(Collection<String>names)
| {"bool" : {"must_not" : {"bool" : {"should" : {"field" : {"name" : "?"}}}}}}
|
| Near
| findByStoreNear
| Not Supported Yet !
|
| True
| findByAvailableTrue
| {"bool" : {"must" : {"field" : {"available" : true}}}}
|
| False
| findByAvailableFalse
| {"bool" : {"must" : {"field" : {"available" : false}}}}
|
| OrderBy
| findByAvailableTrueOrderByNameDesc
| {"sort" : [{ "name" : {"order" : "desc"} }],"bool" : {"must" : {"field" : {"available" : true}}}}
|
例如,我们来按照价格区间查询,定义这样的一个方法:
1)在接口当中定义
package com.itzheng.es.repository;
import com.itzheng.es.pojo.Item;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
import java.util.List;
public interface ItemRepository extends ElasticsearchRepository<Item,Long> {
//上述泛型的第一个参数的实体类类型,第二个是主键ID类型
List findByPriceBetween(double price1, double price2);
}
2)在EsTest编写queryByPriceBetween方法(通过价格的范围查询)
不需要写实现类,然后我们直接去运行:
@Test
public void queryByPriceBetween(){
List items = repository.findByPriceBetween(2000, 4000);
for (Item item : items) {
System.out.println(item);
}
}
5、高级查询
(1)基本查询
先看看基本玩法
@Test
public void testQueryCustom(){
//词条查询
MatchQueryBuilder queryBuilder = QueryBuilders.matchQuery(“title”, “小米”);
Iterable items = repository.search(queryBuilder);
items.forEach(System.out::println);
}
QueryBuilders提供了大量的静态方法,用于生成各种不同类型的查询对象,例如:词条、模糊、通配符等QueryBuilder对象。
结果:
(2)自定义查询
先来看最基本的match query:
@Test
public void testNativeQuery(){
NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
//结果过滤
//添加查询条件
queryBuilder.withQuery(QueryBuilders.matchQuery(“title”,“小米”));
NativeSearchQuery searchQuery = queryBuilder.build();
//执行搜索,获取结果
Page result = repository.search(searchQuery);
//打印总条数
System.out.println(result.getTotalElements());
//打印总页数
System.out.println(result.getTotalPages());
result.forEach(System.out::println);
}
NativeSearchQueryBuilder:Spring提供的一个查询条件构建器,帮助构建json格式的请求体
Page<item>
:默认是分页查询,因此返回的是一个分页的结果对象,包含属性:
-
totalElements:总条数
-
totalPages:总页数
-
Iterator:迭代器,本身实现了Iterator接口,因此可直接迭代得到当前页的数据
返回结果
(3)分页查询和排序
利用NativeSearchQueryBuilder
可以方便的实现分页:
需要再添加一些数据方便测试
@Test
public void indexList(){
List list = new ArrayList<>();
list.add(new Item(9L, “小米手机7”, “手机”, “小米”, 3299.00, “http://image.leyou.com/13123.jpg”));
list.add(new Item(10L, “坚果手机R1”, “手机”, “锤子”, 3699.00, “http://image.leyou.com/13123.jpg”));
list.add(new Item(11L, “华为META10”, “手机”, “华为”, 4499.00, “http://image.leyou.com/13123.jpg”));
list.add(new Item(12L, “小米Mix2S”, “手机”, “小米”, 4299.00, “http://image.leyou.com/13123.jpg”));
list.add(new Item(13L, “荣耀V10”, “手机”, “华为”, 2799.00, “http://image.leyou.com/13123.jpg”));
repository.saveAll(list);
}
再次测试
@Test
public void testNativeQuery(){
// 构建查询条件
NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
// 添加基本的分词查询
queryBuilder.withQuery(QueryBuilders.termQuery(“title”, “手机”));
// 初始化分页参数
int page = 0;
int size = 3;
// 设置分页参数
queryBuilder.withPageable(PageRequest.of(page, size));
// 执行搜索,获取结果
Page items = this.repository.search(queryBuilder.build());
// 打印总条数
System.out.println(items.getTotalElements());
最后
针对最近很多人都在面试,我这边也整理了相当多的面试专题资料,也有其他大厂的面经。希望可以帮助到大家。
最新整理面试题
上述的面试题答案都整理成文档笔记。也还整理了一些面试资料&最新2021收集的一些大厂的面试真题
最新整理电子书
最新整理大厂面试文档
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
list.add(new Item(12L, “小米Mix2S”, “手机”, “小米”, 4299.00, “http://image.leyou.com/13123.jpg”));
list.add(new Item(13L, “荣耀V10”, “手机”, “华为”, 2799.00, “http://image.leyou.com/13123.jpg”));
repository.saveAll(list);
}
再次测试
@Test
public void testNativeQuery(){
// 构建查询条件
NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
// 添加基本的分词查询
queryBuilder.withQuery(QueryBuilders.termQuery(“title”, “手机”));
// 初始化分页参数
int page = 0;
int size = 3;
// 设置分页参数
queryBuilder.withPageable(PageRequest.of(page, size));
// 执行搜索,获取结果
Page items = this.repository.search(queryBuilder.build());
// 打印总条数
System.out.println(items.getTotalElements());
最后
针对最近很多人都在面试,我这边也整理了相当多的面试专题资料,也有其他大厂的面经。希望可以帮助到大家。
最新整理面试题
[外链图片转存中…(img-H9OUCWEt-1714856740886)]
上述的面试题答案都整理成文档笔记。也还整理了一些面试资料&最新2021收集的一些大厂的面试真题
最新整理电子书
[外链图片转存中…(img-x7shcZr6-1714856740886)]
最新整理大厂面试文档
[外链图片转存中…(img-lQCuDare-1714856740887)]
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。