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;
}
}