POM.XML
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.bawei</groupId>
<artifactId>1709d_es</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<!-- elasticsearch和spring的整合包 -->
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-elasticsearch</artifactId>
<version>3.1.2.RELEASE</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.1.2.RELEASE</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
</dependencies>
<!-- 编译 -->
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
创建spring-elasticsearch.xml的配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:elasticsearch="http://www.springframework.org/schema/data/elasticsearch"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/data/elasticsearch http://www.springframework.org/schema/data/elasticsearch/spring-elasticsearch.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 扫描Dao包,自动创建实例 -->
<elasticsearch:repositories base-package="com.haoge.dao" />
<!-- 扫描Service包,创建Service的实体 -->
<!-- <context:component-scan base-package="com.haoge.service" /> --> <!-- 配置elasticSearch的连接 -->
<!-- es提供了2个端口号:9200和9300
9200:对浏览器暴露的端口号
9300:是对java编程需要操作es所暴露的端口号
-->
<elasticsearch:transport-client id="client"
cluster-nodes="192.168.237.129:9300" /> <!-- spring data elasticSearcheDao 必须继承 ElasticsearchTemplate -->
<bean id="elasticsearchTemplate"
class="org.springframework.data.elasticsearch.core.ElasticsearchTemplate">
<constructor-arg name="client" ref="client"></constructor-arg>
</bean>
</beans>
修改配置文件中的相关信息
- 扫描包的路径
- ip地址
进行数据的增删改查操作
第一种方法
1. 创建ArticleRepository 接口 让其继承ElasticsearchRepository接口,进行简单的CRUD操作
//让ArticleRepository继承ElasticsearchRepository,此时这个借口就自动具备了简单的CRUD操作的功能
// Article操作的实体类类型 ,Integer实体类主键类型
public interface ArticleRepository extends ElasticsearchRepository<Article,Integer >{
//定义根据标题查询的抽象方法
//疑问?为什么在这里定义一个抽象方法,就可以直接调用使用了呢?
//这个方法名称不是乱写的,如果要查询,必须findByTitle,findByTitleAndContent,findByTitleOrContent
List<Article> findByTitle(String title);
//根据标题或内容查询
List<Article> findByTitleOrContent(String title,String content);
}
该类定义的查询方法名必须遵守规则(findBy*****)
2. 创建实体类Article
//索引名称和类型名称一律小写(如果是大写,就会报错)
//indexName相当于数据库,type相当于数据表
@Document(indexName="article",type="article")
public class Article implements Serializable{
@Id
private Integer id;
// Field的相关参数的意义 1.是否对此字段建立索引,2.是否对此字段的值进行存储,3.对此字段的值分词方式是ik_smart,4.搜索关键字是否分词5.指定字段值的类型
@Field(index=true,store=true,analyzer="ik_smart",searchAnalyzer="ik_smart",type=FieldType.text)
private String title;
// 1.是否对此字段建立索引,2.是否对此字段的值进行存储,3.对此字段的值分词方式是ik_smart,4.搜索关键字是否分词5.指定字段值的类型
@Field(index=true,store=true,analyzer="ik_smart",searchAnalyzer="ik_smart",type=FieldType.text)
private String content;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
@Override
public String toString() {
return "Article [id=" + id + ", title=" + title + ", content=" + content + "]";
}
}
3. 开启elasticsearch和elasticsearch的头文件
启动elasticsearch的操作一定要在非root的用户
切换用户 su es cd elasticsearch-6.6.2目录下
开启:bin/elasticseeeearch (-d)后台启动
开启头文件 cd/elasticsearch-head-master
cnpm run start
192.168.237.129:9200(9100)9300
4. 创建测试类,进行数据增删改查的测试
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:spring-elasticsearch.xml")
public class EsTest {
@Autowired
ArticleRepository articleRepository;
@Test
//测试添加
public void add() {
Article article = new Article();
article.setId(3);
article.setTitle("森林狼啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊26记三分的最新相关信息");
article.setContent("打疯啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊了!142-115大胜快船!森林狼26记三分 上海热线\r\n" +
"并且全队狂轰26记三分球打破了球队历史记录! 在比赛之前,快船36胜16负,排在西部第三,森林狼16胜35负,排在西部倒数第二,可以说两队的实力相差悬殊,快...");
Article save = articleRepository.save(article);
System.out.println("添加成功");
}
@Test
//测试修改
public void update() {
Article article = new Article();
article.setId(3);
article.setTitle("奥斯卡颁奖的最新相关信息");
article.setContent("2小时前 乌拉乌拉卡夫卡 很卡获得了奥斯卡.");
Article save = articleRepository.save(article);
System.out.println("修改成功");
}
//测试删除
@Test
public void delete() {
articleRepository.deleteById(2);
System.out.println("删除成功");
}
@Test
//测试查询
public void select() {
List<Article> articleList = articleRepository.findByTitleAndContent("三分","打疯了");
for (Article article : articleList) {
System.out.println(article);
}
}
5.结果
第二种方法
1.创建实体类Student
@Document(type = "student",indexName = "cms")
public class Student {
@Id
private Integer id;
@Field(fielddata = true)
private String name;
private Date birthday;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public Student() {
super();
// TODO Auto-generated constructor stub
}
public Student(Integer id, String name, Date birthday) {
super();
this.id = id;
this.name = name;
this.birthday = birthday;
}
@Override
public String toString() {
return "Student [id=" + id + ", name=" + name + ", birthday=" + birthday + "]";
}
}
2.创建测试类
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:spring-elasticsearch.xml")
public class EsTest {
@Resource
private ElasticsearchTemplate elasticsearchTemplate;
//创建索引
@Test
public void testIndex() {
//创建
elasticsearchTemplate.createIndex("cms");
//删除
elasticsearchTemplate.deleteIndex("cms");
System.out.println("创建完毕");
}
//插入数据
@Test
public void addTest() {
//批量添加
for (int i = 4; i <=100; i++) {
Student student = new Student(i,"宋江"+i,new Date());
IndexQuery query = new IndexQueryBuilder().withId(student.getId().toString()).withObject(student).build();
elasticsearchTemplate.index(query);
System.out.println("插入完毕");
}
//第一种方式
IndexQuery query = new IndexQuery();
query.setId(student.getId()+""); query.setObject(student);
//第二中方式
IndexQuery query = new IndexQueryBuilder().withId(student.getId().toString()).withObject(student).build();
elasticsearchTemplate.index(query);
System.out.println("插入完毕");
}
//修改数据
@Test
public void updTest() {
Student student = new Student(1,"及时雨",new Date());
//第一种方式
IndexQuery query = new IndexQuery();
query.setId(student.getId()+""); query.setObject(student);
//第二种方式
IndexQuery query = new IndexQueryBuilder().withId(student.getId().toString()).withObject(student).build();
elasticsearchTemplate.index(query);
System.out.println("修改完毕");
}
//删除数据
@Test
public void delTest() {
elasticsearchTemplate.delete(Student.class, 2+"");
System.out.println("删除完毕");
}
//查询数据
@Test
public void findOneTest() {
//创建查询条件
GetQuery query = new GetQuery();
query.setId("3");
Student student = elasticsearchTemplate.queryForObject(query , Student.class);
System.out.println(student.toString());
}
//查询所有数据
@Test
public void findAllTest() {
//构造器 默认一次查询10条记录
SearchQuery query = new NativeSearchQueryBuilder().build();
List<Student> queryForList = elasticsearchTemplate.queryForList(query , Student.class);
for (Student student : queryForList) {
System.out.println(student);
}
}
//模糊查询
@Test
public void findMHTest() {
//封装模糊查询条件
QueryBuilder queryBuilder = QueryBuilders.multiMatchQuery("及", "name");
//构造器 默认一次查询10条记录
SearchQuery query = new NativeSearchQueryBuilder().withQuery(queryBuilder).build();
List<Student> queryForList = elasticsearchTemplate.queryForList(query , Student.class);
for (Student student : queryForList) {
System.out.println(student);
}
}
//分页查询
@Test
public void pageTest() {
//封装分页查询条件, 当前页,每页条数,排序方式,排序字段
Pageable pageable = PageRequest.of(1, 20, Sort.by(Direction.ASC, "name"));
//封装查询对象
SearchQuery build = new NativeSearchQueryBuilder().withPageable(pageable).build();
List<Student> queryForList = elasticsearchTemplate.queryForList(build, Student.class);
for (Student student : queryForList) {
System.out.println(student);
}
}
//迷糊+分页查询
@Test
public void pageAndMHTest() {
//封装分页查询条件, 当前页,每页条数,排序方式,排序字段
Pageable pageable = PageRequest.of(1, 20, Sort.by(Direction.ASC, "id"));
QueryBuilder queryBuilder =QueryBuilders.multiMatchQuery("宋", "name");
//封装查询对象
SearchQuery build = new NativeSearchQueryBuilder().withQuery(queryBuilder ).withPageable(pageable).build();
List<Student> queryForList = elasticsearchTemplate.queryForList(build, Student.class);
for (Student student : queryForList) {
System.out.println(student);
}
}
//高亮查询
@Test
public void highLightTest() {
// 模板对象 实体类的class对象 实体类中成员变量是其他实体类对象,list类型
//ESUtils.selectObjects(elasticsearchTemplate ,clazz, classes,
// 当前页从0开始 每页条数 排序字段 要查询的字段, String数组 要查询的数据
//page, pageSize, sortField, fieldNames, value)
AggregatedPage<Student> selectObjects = ESUtils.selectObjects(elasticsearchTemplate, Student.class, null, 0, 20, "id", new String[] {"name"}, "宋");
List<Student> list = selectObjects.getContent();
for (Student student : list) {
System.out.println(student);
}
}
}
注:高亮查询的工具类(该工具类非本人所写)
public class ESUtils {
private static Logger logger = Logger.getLogger(ESUtils.class);
/**
* 保存及更新方法
*
* @param elasticsearchTemplate
* @param id
* @param object
*/
public static void saveObject(ElasticsearchTemplate elasticsearchTemplate, String id, Object object) {
// 创建所以对象
IndexQuery query = new IndexQueryBuilder().withId(id).withObject(object).build();
// 建立索引
elasticsearchTemplate.index(query);
}
/**
* 批量删除
*
* @param elasticsearchTemplate
* @param clazz
* @param ids
*/
public static void deleteObject(ElasticsearchTemplate elasticsearchTemplate, Class<?> clazz, Integer ids[]) {
for (Integer id : ids) {
// 建立索引
elasticsearchTemplate.delete(clazz, id + "");
}
}
/**
*
* @Title: selectById
* @Description: 根据id在es服务启中查询对象
* @param elasticsearchTemplate
* @param clazz
* @param id
* @return
* @return: Object
*/
public static Object selectById(ElasticsearchTemplate elasticsearchTemplate, Class<?> clazz, Integer id) {
GetQuery query = new GetQuery();
query.setId(id + "");
return elasticsearchTemplate.queryForObject(query, clazz);
}
// 查询操作
/**
*
* @param elasticsearchTemplate 模板对象
* @param clazz 实体类的class对象
* @param classes 实体类中实体类型的成员变量的类的class集合
* @param page 当前页,从0开始
* @param pageSize 每页的条数
* @param sortField 根据这个字段进行排序
* @param fieldNames 要搜索的字段名
* @param value 具体要搜索的数据
* @return
*/
public static <T> AggregatedPage<T> selectObjects(ElasticsearchTemplate elasticsearchTemplate, Class<T> clazz,
List<Class> classes,Integer page, Integer pageSize, String sortField, String fieldNames[], String value) {
AggregatedPage<T> pageInfo = null;
logger.info("采用es进行数据库的查询操作开始!!!!!!!!!!!!!!!!!!!!!!!!");
// 创建Pageable对象
final Pageable pageable = PageRequest.of(page, pageSize, Sort.by(Sort.Direction.ASC, sortField));
//查询对象
SearchQuery query = null;
//查询条件高亮的构建对象
QueryBuilder queryBuilder = null;
if (value != null && !"".equals(value)) {
// 高亮拼接的前缀与后缀
String preTags = "<font color=\"red\">";
String postTags = "</font>";
// 定义创建高亮的构建集合对象
HighlightBuilder.Field highlightFields[] = new HighlightBuilder.Field[fieldNames.length];
for (int i = 0; i < fieldNames.length; i++) {
// 这个代码有问题
highlightFields[i] = new HighlightBuilder.Field(fieldNames[i]).preTags(preTags).postTags(postTags);
}
// 创建queryBuilder对象
queryBuilder = QueryBuilders.multiMatchQuery(value, fieldNames);
query = new NativeSearchQueryBuilder().withQuery(queryBuilder).withHighlightFields(highlightFields)
.withPageable(pageable).build();
pageInfo = elasticsearchTemplate.queryForPage(query, clazz, new SearchResultMapper() {
@Override
public <T> AggregatedPage<T> mapResults(SearchResponse response, Class<T> clazz, Pageable pageable1) {
List<T> content = new ArrayList<T>();
long total = 0l;
try {
// 查询结果
SearchHits hits = response.getHits();
if (hits != null) {
//获取总记录数
total = hits.getTotalHits();
// 获取结果数组
SearchHit[] searchHits = hits.getHits();
// 判断结果
if (searchHits != null && searchHits.length > 0) {
// 遍历结果
for (int i = 0; i < searchHits.length; i++) {
// 对象值
T entity = clazz.newInstance();
// 获取具体的结果
SearchHit searchHit = searchHits[i];
// 获取对象的所有的字段
Field[] fields = clazz.getDeclaredFields();
// 遍历字段对象
for (int k = 0; k < fields.length; k++) {
// 获取字段对象
Field field = fields[k];
// 暴力反射
field.setAccessible(true);
// 字段名称
String fieldName = field.getName();
if (!fieldName.equals("serialVersionUID")) {
HighlightField highlightField = searchHit.getHighlightFields()
.get(fieldName);
if (highlightField != null) {
// 高亮 处理 拿到 被<font color='red'> </font>结束所包围的内容部分
String value = highlightField.getFragments()[0].toString();
// 注意一下他是否是 string类型
field.set(entity, value);
} else {
//获取某个字段对应的 value值
Object value = searchHit.getSourceAsMap().get(fieldName);
// System.out.println(value);
// 获取字段的类型
Class<?> type = field.getType();
if (type == Date.class) {
if (value != null) {
//如果不为空,则转换成Date类型
Date value_date = null;
if(value.getClass() == Long.class) {
//如果是Long类型
value_date = new Date(Long.valueOf(value + ""));
}else {
//如果是String类型
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
value_date = sdf.parse(value.toString());
}
// bug
field.set(entity, value_date);
}
} else if (type.isEnum()){
if(value != null) {
//枚举
field.set(entity, Enum.valueOf((Class<Enum>) type, value.toString()));
}
} else if (classes != null && classes.contains(type)){
if(value != null) {
//将实体类对象实例化
Object obj = getEntityObject(value, type ,classes);
//将对象赋值
field.set(entity, obj);
}
} else{
field.set(entity, value);
}
}
}
}
content.add(entity);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return new AggregatedPageImpl<T>(content, pageable, total);
}
//递归方法,生成实体类对象
private Object getEntityObject(Object value, Class<?> type, List<Class> classes)
throws InstantiationException, IllegalAccessException, ParseException {
//实体类
Object obj = type.newInstance();
Map map = (HashMap)value;
//获取所有字段
Field[] fields2 = type.getDeclaredFields();
for (Field field2 : fields2) {
//排除静态变量和常量
int mod = field2.getModifiers();
if (Modifier.isStatic(mod) || Modifier.isFinal(mod)) {
continue;
}
//暴力反射
field2.setAccessible(true);
//从map中获取对应的字段的值
Object value2 = map.get(field2.getName());
//处理日期Date类型
Class<?> type2 = field2.getType();
if (type2 == Date.class) {
if (value2 != null) {
//如果不为空,则转换成Date类型
Date value2_date = null;
if(value2.getClass() == Long.class) {
//如果是Long类型
value2_date = new Date(Long.valueOf(value2 + ""));
}else {
//如果是String类型
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
value2_date = sdf.parse(value2.toString());
}
// bug
field2.set(obj, value2_date);
}
}else if (type2.isEnum()){
if(value2 != null) {
//枚举
field2.set(obj, Enum.valueOf((Class<Enum>) type2, value2.toString()));
}
} else if (classes != null && classes.contains(type2)){
if(value2 != null) {
//将实体类对象实例化
Object obj2 = getEntityObject(value2, type2 ,classes);
//将对象赋值
field2.set(obj, obj2);
}
} else {
field2.set(obj, value2);
}
}
return obj;
}
});
} else {
// 没有查询条件的的时候,获取es中的全部数据 分页获取
query = new NativeSearchQueryBuilder().withPageable(pageable).build();
pageInfo = elasticsearchTemplate.queryForPage(query, clazz);
}
return pageInfo;
}
}