什么是es?
elasticsearch(简称为es)是一个开源的分布式搜索引擎,用于全文搜索、实时分析和可视化。它建立在apache lucene搜索引擎库的基础上,提供了restful api,支持分布式架构和水平扩展,特别适用于处理大规模的非结构化或半结构化数据。
elasticsearch与传统数据库查询的区别:
-
搜索引擎特性: elasticsearch是一个搜索引擎,其主要设计目标是支持高效的全文搜索和实时分析。它专注于处理大量文本数据,支持复杂的全文搜索查询,例如模糊搜索、词组匹配、范围查询等。传统数据库主要面向结构化数据,更适用于关系型查询。
-
分布式和水平扩展: elasticsearch是分布式的,它可以在多个节点上运行,并能够水平扩展以处理大规模数据。传统数据库通常在单个节点上运行,并且通常需要垂直扩展(增加服务器性能)来处理更大的负载。
-
schema-less(无模式): elasticsearch是无模式的,意味着你不需要在索引中预定义数据结构。你可以直接插入数据,elasticsearch会根据数据自动推断其类型。传统数据库需要在创建表时定义模式。
-
实时性: elasticsearch提供实时索引和搜索功能,数据几乎立即可用于搜索。传统数据库的实时性可能受到数据复制和索引的影响。
-
多语言支持: elasticsearch支持多种查询语言,例如查询字符串、dsl(domain specific language)等,使其更易于使用和集成。传统数据库通常使用sql。
要在spring boot项目中集成elasticsearch,首先需要添加相应的依赖,然后配置elasticsearch的连接信息,最后通过spring data elasticsearch或者elasticsearch的java rest客户端来与elasticsearch进行交互。
springboot整合elasticsearch的步骤:
0.代码层级结构
1. 添加依赖
在pom.xml中添加spring data elasticsearch依赖:
<dependency>
<groupid>org.springframework.boot</groupid>
<artifactid>spring-boot-starter-data-elasticsearch</artifactid>
</dependency>
2. 配置elasticsearch连接信息
在application.properties或(application.yml)中配置elasticsearch连接信息,如下:
spring.elasticsearch.uris=http://localhost:9200
spring:
elasticsearch:
uris: http://localhost:9200
如果elasticsearch没有设置用户名和密码,这可能就足够了。如果需要认证,可以使用以下配置:
spring.elasticsearch.username=your_username
spring.elasticsearch.password=your_password
spring:
elasticsearch:
uris: http://localhost:9200
username:your_username
password:your_password
3. 创建实体类
创建一个简单的实体类,使用@document注解指定索引和类型:
import lombok.data;
import org.springframework.data.annotation.id;
import org.springframework.data.elasticsearch.annotations.document;
/**
* @document(indexname = "user-demo") 索引名称为user-demo
* */
@data
@document(indexname = "user-demo")
public class user {
@id
private string id;
private string username;
private string address;
private integer age;
private string gender;
}
4. 使用spring data elasticsearch进行操作
创建一个usermapper接口,继承自elasticsearchrepository:
import com.example.demoes.entity.user;
import org.springframework.data.domain.page;
import org.springframework.data.domain.pageable;
import org.springframework.data.elasticsearch.repository.elasticsearchrepository;
import org.springframework.stereotype.repository;
import java.util.list;
/**
* 这些方法的名称遵循一种命名约定,这种约定将方法名中的关键词(如 findby、like、ignorecase 等)与实体类(user)的属性名相关联。
* 这样,spring data elasticsearch 可以根据方法名自动生成相应的查询。
*
* 在spring data elasticsearch中,查询方法的命名约定依赖于一些关键词和命名规范,这些关键词用于描述要执行的查询操作。以下是一些常见的关键词和它们的含义:
*
* findby:指定查询的条件的前缀,后面通常跟随实体类的属性名。例如,findbyusername 表示要根据用户名进行查询。
*
* like:用于模糊查询,通常与属性名一起使用。例如,findbyusernamelike 表示要进行用户名的模糊查询。
*
* ignorecase:用于不区分大小写的查询,通常与属性名一起使用。例如,findbyusernameignorecase 表示不区分大小写地查询用户名。
*
* containing:用于包含查询,通常与属性名一起使用。例如,findbyusernamecontaining 表示包含指定内容的查询。
*
* and 和 or:用于构建复合查询条件。例如,findbyusernameandage 表示根据用户名和年龄进行查询。
*
* orderby:用于指定结果的排序方式。例如,findbyageorderbyusernamedesc 表示根据年龄查询并按用户名降序排序。
*
* page 和 iterable:用于指定查询结果的返回类型。例如,page<user> 表示返回分页结果,iterable<user> 表示返回一个列表。
*
* 其他属性名:您可以根据实体类的属性名来定义查询条件。例如,如果实体类有一个属性为 email,您可以编写 findbyemail 方法来根据邮箱进行查询。
* */
@repository
public interface usermapper extends elasticsearchrepository<user,string> {
/**
*自定义查询
* */
list<user> findbyaddresslikeignorecaseorderbyagedesc(string address);
page<user> findbyusernamecontaining(string username, pageable page);
user findbyage(integer age);
list<user> findbygender(string gender);
long count();
boolean existsbyid();
}
5.测试
在测试中使用spring boot的@springboottest注解,来验证elasticsearch是否正常工作。
import com.example.demoes.entity.user;
import com.example.demoes.mapper.usermapper;
import org.junit.jupiter.api.test;
import org.springframework.beans.factory.annotation.autowired;
import org.springframework.boot.test.context.springboottest;
import org.springframework.data.domain.page;
import org.springframework.data.domain.pagerequest;
import org.springframework.data.elasticsearch.core.elasticsearchresttemplate;
import java.util.*;
@springboottest
class demoesapplicationtests {
// @resource
@autowired
private usermapper usermapper;
@autowired
private elasticsearchresttemplate elasticsearchresttemplate;
@test
void add() {
for (int i = 2; i < 11; i++) {
user user = new user();
user.setid(i + "");
user.setusername("zhangsan" + i);
user.setgender("男");
user.setage(i + i);
user.setaddress("河北省" + i);
//直接将数据保存到es中,索引名称为user-demo,在user对象中设置的
//通过kibana进行查询get /user-demo/_search
user save = usermapper.save(user);
system.out.println("save = " + save);
}
}
@test
void delete() {
string id = "9";
usermapper.deletebyid(id);
}
@test
void update() {
user updateuser = new user();
updateuser.setid("9");
updateuser.setusername("lisi");
updateuser.setgender("女");
updateuser.setaddress("北京市");
updateuser.setage(39);
user save = usermapper.save(updateuser);
system.out.println("save = " + save);
}
@test
void find() {
//模糊查询。精确查询
iterable<user> all = usermapper.findall();
list<user> list = new arraylist<>();
for (user user : all) {
list.add(user);
}
// 使用collections.sort方法按照用户的id进行排序
// collections.sort(list, comparator.comparing(user::getid));
// 使用自定义比较器按照用户的id进行排序
collections.sort(list, new comparator<user>() {
@override
public int compare(user user1, user user2) {
// 假设id是字符串类型
return user1.getusername().compareto(user2.getusername());
}
});
// 使用流(stream)按照用户的id进行排序
/*list<user> sortedlist = list.stream()
.sorted(comparator.comparing(user::getid))
.collect(collectors.tolist());*/
// 现在list中的用户已按照id升序排列
for (user user : list) {
system.out.println("user = " + user);
}
}
@test
void findbyid() {
//注意这里的id是字符串类型,然后usermapper中继承的id也必须是string类型
optional<user> byid = usermapper.findbyid("4");
system.out.println("byid = " + byid);
}
@test
void findcount() {
long count = usermapper.count();
system.out.println("count 数 " + count);
}
@test
void existsbyid() {
system.out.println("id是否存在: " + usermapper.existsbyid("1"));
}
@test
void findbyidall() {
arraylist<string> ids = new arraylist<>();
ids.add("3");
ids.add("5");
ids.add("4");
ids.add("66");
//通过ids(集合)进行查询对应的user集合对象
iterable<user> allbyid = usermapper.findallbyid(ids);
for (user user : allbyid) {
system.out.println("user = " + user);
}
}
/**
* 自定义查询
*/
@test
void findbyusernamelike() {
//模糊查询,会通过命名规范进行一个查询
list<user> addr = usermapper.findbyaddresslikeignorecaseorderbyagedesc("河北");
system.out.println("addr = " + addr);
page<user> page = usermapper.findbyusernamecontaining("4", pagerequest.of(0, 100));
system.out.println("page = " + page.getcontent());
user zhanglist = usermapper.findbyage(16);
system.out.println("user = " + zhanglist);
list<user> gender = usermapper.findbygender("女");
system.out.println("gender = " + gender);
}
以上步骤是一个简单的spring boot集成elasticsearch的示例。你可以根据你的实际需求进行更复杂的配置和操作。
发表评论