springBoot + Elasticsearch简单案例实现

发布于:2021-12-02 11:17:15

springBoot+Elasticsearch简单demo

创建springBoot项目:结构如下


xml配置:


spring:
data:
elasticsearch:
cluster-name: my-application
cluster-nodes: 127.0.0.1:9300 # 程序连接

pom配置:



UTF-8
UTF-8
1.8




org.springframework.boot
spring-boot-starter-web


org.springframework.boot
spring-boot-starter-data-elasticsearch


org.springframework.boot
spring-boot-starter-test
test


org.projectlombok
lombok
1.16.20




映射-注解

Spring Data通过注解来声明字段的映射属性,有下面的三个注解:


@Document 作用在类,标记实体类为文档对象,一般有两个属性
indexName:对应索引库名称type:对应在索引库中的类型shards:分片数量,默认5replicas:副本数量,默认1 @Id 作用在成员变量,标记一个字段作为id主键@Field 作用在成员变量,标记为文档的字段,并指定字段映射属性:
type:字段类型,是枚举:FieldType,可以是text、long、short、date、integer、object等
text:存储数据时候,会自动分词,并生成索引keyword:存储数据时候,不会分词建立索引Numerical:数值类型,分两类
基本数据类型:long、interger、short、byte、double、float、half_float浮点数的高精度类型:scaled_float
需要指定一个精度因子,比如10或100。elasticsearch会把真实值乘以这个因子后存储,取出时再还原。 Date:日期类型
elasticsearch可以对日期格式化为字符串存储,但是建议我们存储为毫秒值,存储为long,节省空间。 index:是否索引,布尔类型,默认是truestore:是否存储,布尔类型,默认是falseanalyzer:分词器名称,这里的ik_max_word即使用ik分词器

了解注解后,创建pojo,即要索引的对象:


@Document(indexName = "item", type = "item", shards = 1, replicas = 0)
@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class Item {

@Id
private Long id;

@Field(type = FieldType.Text, analyzer = "ik_max_word")
private String title;

@Field(type = FieldType.Text)
private String category;

@Field(type = FieldType.Text)
private String brand;

@Field(type = FieldType.Text)
private Double price;

@Field(type = FieldType.Text, index = false)
private String images;
}


创建Repository接口:


import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;

import java.util.List;

public interface EsRepository extends ElasticsearchRepository {


在测试类中写如下代码,创建,删除索引:


@RunWith(SpringRunner.class)
@SpringBootTest(classes = EsDemoApplication.class)
public class EsDemoApplicationTests {

@Autowired
private ElasticsearchTemplate elasticsearchTemplate;

@Autowired
private EsRepository esRepository;

@Test
public void CreateIndex() {
// 创建索引,会根据Item类的@Document注解信息来创建
elasticsearchTemplate.createIndex(Item.class);
// 配置映射,会根据Item类中的id、Field等字段来自动完成映射
elasticsearchTemplate.putMapping(Item.class);
}

/**
* 删除数据库
*/
@Test
public void testDeleteIndex() {
elasticsearchTemplate.deleteIndex(Item.class);
}


然后访问 localhost:9100
查看结果如下:

索引创建成功!!


添加数据
测试类中继续写:


/**
* 保存多条数据
*/
@Test
public void testSaveItemList() {
Item item2 = new Item(10L, "华为手机nate20Pro", "手机", "华为", 699.0, "https://img10.360buyimg.com/cms/jfs/t28402/77/271791263/9559/3c4ae8ad/5bf80a4eN1a99b125.jpg");
Item item3 = new Item(21L, "iphone x", "手机", "苹果", 799.0, "https://img10.360buyimg.com/cms/jfs/t28402/77/271791263/9559/3c4ae8ad/5bf80a4eN1a99b125.jpg");
Item item4 = new Item(32L, "iphone xs", "手机", "苹果", 899.0, "https://img10.360buyimg.com/cms/jfs/t28402/77/271791263/9559/3c4ae8ad/5bf80a4eN1a99b125.jpg");
Item item5 = new Item(43L, "iphone xs Max", "手机", "苹果", 999.0, "https://img10.360buyimg.com/cms/jfs/t28402/77/271791263/9559/3c4ae8ad/5bf80a4eN1a99b125.jpg");

ArrayList list = new ArrayList<>();
list.add(item2);
list.add(item3);
list.add(item4);
list.add(item5);

esRepository.saveAll(list);
}

运行,ok


对数据进行简单操作:


@Test
public void testFindAll() {
// 查找所有
Iterable item = esRepository.findAll();
Iterator it = item.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
// 分页查找
Page page = esRepository.findAll(PageRequest.of(1, 5));

for(Item item:page){
System.out.println(item);
}

// 3 排序
Iterable iterable = esRepository.findAll(Sort.by("price").descending());
Iterator it = iterable.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
}


Spring Data 的另一个强大功能,是根据方法名称自动实现功能。

比如:你的方法名叫做:findByTitle,那么它就知道你是根据title查询,然后自动帮你完成,无需写实现类。


当然,方法名称要符合一定的约定:


KeywordSample
AndfindByTitleAndPricefindBy属性名1And属性名2
OrfindByTitleOrPrice
Is=findByTitle
NotfindByTitleNot
BetweenfindByPriceBetween
LessThanEqualfindByPriceLessThan
GreaterThanEqualfindByPriceGreaterThan
BeforefindByPriceBefore
AfterfindByPriceAfter
LikefindByNameLike
StartingWithfindByNameStartingWith
EndingWithfindByNameEndingWith
Contains/ContainingfindByNameContaining
InfindByNameIn(Collectionnames)
NotInfindByNameNotIn(Collectionnames)
NearfindByStoreNear
TruefindByAvailableTrue
FalsefindByAvailableFalse
OrderByfindByAvailableTrueOrderByNameDesc

在EsRepository中可自定义方法:


/**
* 价格在xx-yy以内
* @param price1
* @param price2
* @return
*/
public List findByPriceBetween(Double price1,Double price2);

/**
* 价格在xx-yy以内,并且根据价格倒序排序
* @param price1
* @param price2
* @return
*/
public List findByPriceBetweenOrderByPriceDesc(Double price1, Double price2);

/**
*
* @param title:支持模糊匹配
* @param price:精确查找
* @return
*/
public List findByTitleAndPrice(String title,Double price);

/**模糊匹配
*
* @param title
* @return
*/
public List findByTitle(String title);

测试自定义方法:


/**
* 测试自定义方法
*/
@Test
public void testMethods(){
// List list = itemRepository.findByPriceBetween(5000.0, 7000.0);
// List list = itemRepository.findByPriceBetweenOrderByPriceDesc(1000.0, 7000.0);

// List list = itemRepository.findByTitleAndPrice("手机", 299.0);

List list = itemRepository.findByTitle("手机");

for(Item item:list){
System.out.println(item);
}
}

运行,ok


自定义查询

matchQuery:词条匹配,会分词,底层使用的是termQuery,但是它会对条件进行分词之后再去匹配

TermQuery:词条匹配,不会分词

wildcardQuery:通配符匹配

booleanQuery:布尔查询

fuzzyQuery:模糊匹配


测试 match query:


@Test
public void search(){
// 构建查询条件
NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
// 添加基本分词查询
queryBuilder.withQuery(QueryBuilders.matchQuery("title", "小米手机"));
// 搜索,获取结果
Page items = this.itemRepository.search(queryBuilder.build());
// 总条数
long total = items.getTotalElements();
System.out.println("total = " + total);
for (Item item : items) {
System.out.println(item);
}
}

NativeSearchQueryBuilder:Spring提供的一个查询条件构建器,帮助构建json格式的请求体
Page`:默认是分页查询,因此返回的是一个分页的结果对象,包含属性:


totalElements:总条数totalPages:总页数Iterator:迭代器,本身实现了Iterator接口,因此可直接迭代得到当前页的数据

测试termQuery


@Test
public void testTermQuery(){

// 查询条件生成器
NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();
builder.withQuery(QueryBuilders.termQuery("title","小米"));
// 查询 自动分页 ,默认查找第一页的10条数据
Page list = this.itemRepository.search(builder.build());

for(Item item:list){
System.out.println(item);
}
}

测试 fuzzyQuery:


@Test
public void testFuzzyQuery(){
NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();
builder.withQuery(QueryBuilders.fuzzyQuery("title","faceoooo"));

Page list = this.itemRepository.search(builder.build());
for(Item item:list){
System.out.println(item);
}
}

测试 booleanQuery:



@Test
public void testBooleanQuery(){
NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();
builder.withQuery(QueryBuilders.boolQuery().must(QueryBuilders.termQuery("title","手机"))
.must(QueryBuilders.termQuery("brand","小米"))
);

Page list = this.itemRepository.search(builder.build());
for(Item item:list){
System.out.println(item);
}
}

测试 RangeQuery:


@Test
public void testRangeQuery(){
NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
// queryBuilder.withQuery(QueryBuilders.fuzzyQuery("title","小目"));


queryBuilder.withQuery(QueryBuilders.rangeQuery("price").from(3000).to(4000));

Page page = itemRespository.search(queryBuilder.build());

for(Item i:page){
System.out.println(i);
}
}

运行,OK

相关推荐

最新更新

猜你喜欢