本文將基於springboot 2.1.8.RELEASE
來整合 Elasticsearch
java
環境:elasticsearch-5.6.16
node
舒適小提示:ES服務端
或Kibana客戶端
官網下載地址: https://www.elastic.co/downloads/past-releases
pom.xml
中引入es依賴<!-- spring data es --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-elasticsearch</artifactId> </dependency>
application.yml
中配置esspring: # es相關配置 data: elasticsearch: # 配置集羣名 cluster-name: elasticsearch # 訪問 es服務端 `http://127.0.0.1:9200/` 填寫 `cluster_name` 對應的值 # 配置節點信息,逗號分隔,若是沒有指定,則啓動ClientNode 【 注:9200->圖形界面端、9300->程序端 】 cluster-nodes: 127.0.0.1:9300 # 開啓 Elasticsearch 倉庫(默認值:true) repositories: enabled: true
如上配置後,能夠先啓動一下項目,可能運行後會出現以下問題:mysql
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'elasticsearchClient' defined in class path resource [org/springframework/boot/autoconfigure/data/elasticsearch/ElasticsearchAutoConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.elasticsearch.client.transport.TransportClient]: Factory method 'elasticsearchClient' threw exception; nested exception is java.lang.IllegalStateException: availableProcessors is already set to [8], rejecting [8]
錯誤緣由:程序的其餘地方使用了Netty,這裏指redis。這影響在實例化傳輸客戶端以前初始化處理器的數量。 實例化傳輸客戶端時,咱們嘗試初始化處理器的數量。 因爲在其餘地方使用Netty,所以已經初始化而且Netty會對此進行防範,所以首次實例化會因看到的非法狀態異常而失敗。
解決:在啓動類中加上以下配置git
System.setProperty("es.set.netty.runtime.available.processors","false");
注:雖然上面的方式能解決錯誤,服務能夠正常啓動,可是啓動測試類時仍是會報錯哦!!!redis
所以es配置文件中需配置在RedisConfig
以前裝配,而且指定初始化時再一次添加忽略es中netty的一些配置!!!spring
ElasticsearchConfig
配置文件以下:sql
@Configuration @AutoConfigureBefore(RedisConfig.class) // `RedisConfig.class`爲redis配置文件 public class ElasticsearchConfig { @PostConstruct void init() { System.setProperty("es.set.netty.runtime.available.processors", "false"); } @Bean(name = "elasticsearchTemplate") public ElasticsearchTemplate elasticsearchTemplate(Client client, ElasticsearchConverter converter) { try { return new ElasticsearchTemplate(client, converter); } catch (Exception ex) { throw new IllegalStateException(ex); } } @Bean public ElasticsearchConverter elasticsearchConverter( SimpleElasticsearchMappingContext mappingContext) { return new MappingElasticsearchConverter(mappingContext); } @Bean public SimpleElasticsearchMappingContext mappingContext() { return new SimpleElasticsearchMappingContext(); } }
若是出現以下問題:數據庫
failed to load elasticsearch nodes : org.elasticsearch.client.transport.NoNodeAvailableException: None of the configured nodes are available: [{#transport#-1}{6VrRZl9ISEy3MT0rx2Vd2w}{127.0.0.1}{127.0.0.1:9300}]
① 嘗試修改es服務端配置文件 network.host: 127.0.0.1
② cluster-name
集羣名是否一致springboot
③ 若是檢查完以上2種狀況後,仍是報一樣的錯誤,就要考慮是否爲版本問題哦,小編剛開始處於新鮮感使用的是目前最新版elasticsearch-7.5.1
,而spring-boot-starter-data-elasticsearch
中的spring-data-elasticsearch3.1.10.RELEASE
版本不支持高版本的es,所以版本選擇要注意哦!!!app
舒適小提示:注意包名不要導錯哦!!!
import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import org.springframework.data.annotation.Id; import org.springframework.data.elasticsearch.annotations.Document; import org.springframework.data.elasticsearch.annotations.Field; import org.springframework.data.elasticsearch.annotations.FieldType; /** * <p> 測試 </p> * * @author : zhengqing * @description : indexName:索引庫 type:類型(可理解爲mysql數據庫中的表名) * @date : 2019/12/27 14:47 */ @Data @NoArgsConstructor @AllArgsConstructor @Document(indexName = "zq_test", type = "user") public class User { @Id private Long id; @Field(type = FieldType.Keyword) private String name; // @Field(type = FieldType.Text, analyzer = "ik_max_word", searchAnalyzer = "ik_max_word") private String intro; @Field(type = FieldType.Integer) private Integer age; }
@Component public interface UserRepository extends ElasticsearchRepository<User, Long> { }
@RunWith(SpringRunner.class) @SpringBootTest(classes = DemoApplication.class) public class ESTest { @Autowired private ElasticsearchTemplate template; /** * 建立索引,而且創建類型映射 */ @Test public void test() throws Exception { // 建立索引 template.createIndex(User.class); // 類型映射 - 自定義映射 template.putMapping(User.class); } }
運行後,在 http://127.0.0.1:5601/app/kibana#/dev_tools 中執行命令 GET zq_test/_mapping/user
查看類型映射
@RunWith(SpringRunner.class) @SpringBootTest(classes = DemoApplication.class) public class ESTest { @Autowired private UserRepository repository; @Test // 新增1個 public void testAdd() throws Exception { User user = new User(1L, "zheng qing", "zheng qing is a programmer!", 18); repository.save(user); } @Test // 批量添加 public void testBatchAdd() throws Exception { List<User> list = new ArrayList<>(); for (int i = 0; i < 20; i++) { User user = new User(i + 2L, "zheng qing" + i + 1, "zheng qing is a programmer!", 18 + i ); list.add(user); } repository.saveAll(list); } @Test // 獲取1個 public void testGetOne() throws Exception { System.out.println(repository.findById(1L)); } @Test // 獲取所有 public void testGetAll() throws Exception { Iterable<User> all = repository.findAll(); for (User user : all) { System.out.println(user); } } @Test // 新增、修改 (判斷是否有id便可~) public void testUpdate() throws Exception { Optional<User> byId = repository.findById(1L); User user = byId.get(); System.out.println(user); user.setName("zq"); repository.save(user); System.out.println(repository.findById(1L)); } @Test // 刪除 public void testDel() throws Exception { repository.deleteById(1L); //repository.deleteAll();; } }
@RunWith(SpringRunner.class) @SpringBootTest(classes = DemoApplication.class) public class ESTest { @Autowired private UserRepository repository; @Test // DSL查詢與過濾+分頁+排序 public void testNativeSearchQueryBuilder() throws Exception { NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder(); BoolQueryBuilder bool = QueryBuilders.boolQuery(); //模糊查詢 bool.must(QueryBuilders.matchQuery("intro", "zheng")); //精確過濾 List<QueryBuilder> filters = bool.filter(); filters.add(QueryBuilders.rangeQuery("age").gte(0).lte(200)); builder.withQuery(bool); //query bool must(filter) //排序 builder.withSort(SortBuilders.fieldSort("age").order(SortOrder.ASC)); //分頁 注:當前頁從0開始 builder.withPageable(PageRequest.of(0, 10)); //截取字段 builder.withSourceFilter(new FetchSourceFilter(new String[]{"name", "age"}, null)); //構造查詢條件 NativeSearchQuery query = builder.build(); //查詢 Page<User> page = repository.search(query); System.out.println("總數:" + page.getTotalElements()); System.out.println("總頁數:" + page.getTotalPages()); for (User user : page.getContent()) { System.out.println(user); } } }