在Elasticsearch中,爲java提供了2種客戶端,一種是REST風格的客戶端,另外一種是Java API的客戶端。https://www.elastic.co/guide/...html
1.REST客戶端
Elasticsearch提供了2種REST客戶端,一種是低級客戶端,一種是高級客戶端。java
2.構造數據node
curl -X POST "http://47.101.129.45:9200/test/house/_bulk?pretty" -H 'Content-Type: application/json' --data-binary ' {"index":{"_index":"test","_type":"house"}} {"id":"1001","title":"整租 · 南丹大樓 1居室 7500","price":"7500"} {"index":{"_index":"test","_type":"house"}} {"id":"1002","title":"陸家嘴板塊,精裝設計一室一廳,可拎包入住誠意租。","price":"8500"} {"index":{"_index":"test","_type":"house"}} {"id":"1003","title":"整租 · 健安坊 1居室 4050","price":"7500"} {"index":{"_index":"test","_type":"house"}} {"id":"1004","title":"整租 · 中凱城市之光+視野開闊+景色秀麗+拎包入住","price":"6500"} {"index":{"_index":"test","_type":"house"}} {"id":"1005","title":"整租 · 南京西路品質小區 21213三軌交匯配套齊* 拎包入住","price":"6000"} {"index":{"_index":"test","_type":"house"}} {"id":"1006","title":"祥康裏簡約風格 *南戶型拎包入住看房隨時","price":"7000"} '
3.REST低級客戶端
1)用IDEA建立SpringBoot工程spring-elasticsearchmysql
<?xml version="1.0" encoding="UTF-8"?> <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 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.2.0.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.example</groupId> <artifactId>elasticsearch</artifactId> <version>0.0.1-SNAPSHOT</version> <name>elasticsearch</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency> <dependency> <groupId>org.elasticsearch.client</groupId> <artifactId>elasticsearch-rest-client</artifactId> <version>6.5.4</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.9.4</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
2)編寫測試web
/** * REST低級客戶端 */ public class TestElasticSearch { private static final ObjectMapper MAPPER = new ObjectMapper(); private RestClient restClient; @Before public void init() { RestClientBuilder restClientBuilder = RestClient.builder( new HttpHost("47.101.129.45", 9200, "http")); restClientBuilder.setFailureListener(new RestClient.FailureListener() { @Override public void onFailure(Node node) { System.out.println("出錯了 -> " + node); } }); this.restClient = restClientBuilder.build(); } @After public void after() throws IOException { restClient.close(); } /** * 查詢集羣狀態 * * @throws IOException */ @Test public void testGetInfo() throws IOException { Request request = new Request("GET", "/_cluster/state"); request.addParameter("pretty", "true"); Response response = this.restClient.performRequest(request); System.out.println(response.getStatusLine()); System.out.println(EntityUtils.toString(response.getEntity())); } /** * 新增數據 * * @throws IOException */ @Test public void testCreateData() throws IOException { Request request = new Request("POST", "/test/house"); request.addParameter("pretty", "true"); Map<String, Object> data = new HashMap<>(); data.put("id", "2001"); data.put("title", "張江高科"); data.put("price", "3500"); request.setJsonEntity(MAPPER.writeValueAsString(data)); Response response = this.restClient.performRequest(request); System.out.println(response.getStatusLine()); System.out.println(EntityUtils.toString(response.getEntity())); } /** * 根據id查詢數據 */ @Test public void testQueryData() throws IOException { Request request = new Request("GET", "/test/house/3xNNOW4BpJzEX51okOM5"); request.addParameter("pretty", "true"); Response response = this.restClient.performRequest(request); System.out.println(response.getStatusLine()); System.out.println(EntityUtils.toString(response.getEntity())); } /** * 搜索數據 */ @Test public void testSearchData() throws IOException { Request request = new Request("POST", "/test/house/_search"); String searchJson = "{\"query\": {\"match\": {\"title\": \"拎包入住\"}}}"; request.setJsonEntity(searchJson); request.addParameter("pretty", "true"); Response response = this.restClient.performRequest(request); System.out.println(response.getStatusLine()); System.out.println(EntityUtils.toString(response.getEntity())); } }
從使用中,能夠看出,基本和咱們使用RESTful api使用幾乎是一致的spring
4.REST高級客戶端
pom.xml引入依賴sql
<dependency> <groupId>org.elasticsearch.client</groupId> <artifactId>elasticsearch-rest-high-level-client</artifactId> <version>6.5.4</version> </dependency>
編寫測試docker
/** * REST高級客戶端 */ public class TestRestHighLevel { private RestHighLevelClient client; @Before public void init() { RestClientBuilder restClientBuilder = RestClient.builder( new HttpHost("47.101.129.45", 9200, "http") ); this.client = new RestHighLevelClient(restClientBuilder); } @After public void after() throws Exception { this.client.close(); } /** * 新增文檔,同步操做 * * @throws Exception */ @Test public void testCreate() throws Exception { Map<String, Object> data = new HashMap<>(); data.put("id", "2002"); data.put("title", "南京西路 拎包入住 一室一廳"); data.put("price", "4500"); IndexRequest indexRequest = new IndexRequest("test", "house").source(data); IndexResponse indexResponse = this.client.index(indexRequest, RequestOptions.DEFAULT); System.out.println(indexResponse); System.out.println("id->" + indexResponse.getId()); System.out.println("index->" + indexResponse.getIndex()); System.out.println("type->" + indexResponse.getType()); System.out.println("version->" + indexResponse.getVersion()); System.out.println("result->" + indexResponse.getResult()); System.out.println("shardInfo->" + indexResponse.getShardInfo()); } /** * 新增文檔,異步操做 */ @Test public void testCreateAsync() throws Exception { Map<String, Object> data = new HashMap<>(); data.put("id", "2003"); data.put("title", "南京東路最新房源二室一廳"); data.put("price", "5500"); IndexRequest indexRequest = new IndexRequest("test", "house").source(data); this.client.indexAsync(indexRequest, RequestOptions.DEFAULT, new ActionListener<IndexResponse>() { @Override public void onResponse(IndexResponse indexResponse) { System.out.println(indexResponse); } @Override public void onFailure(Exception e) { System.out.println(e); } }); Thread.sleep(2000); } /** * 指定返回字段查詢 */ @Test public void testQuery() throws Exception { GetRequest request = new GetRequest("test", "house", "4hN-OW4BpJzEX51oe-Of"); //指定返回字段 String[] includes = new String[]{"title", "id"}; String[] excludes = Strings.EMPTY_ARRAY; FetchSourceContext fetchSourceContext = new FetchSourceContext(true, includes, excludes); request.fetchSourceContext(fetchSourceContext); GetResponse response = this.client.get(request, RequestOptions.DEFAULT); System.out.println("數據 -> " + response); } /** * 判斷是否存在 */ @Test public void testExists() throws Exception { GetRequest getRequest = new GetRequest("test", "house", "4hN-OW4BpJzEX51oe-Of"); //不返回字段 getRequest.fetchSourceContext(new FetchSourceContext(false)); boolean exists = this.client.exists(getRequest, RequestOptions.DEFAULT); System.out.println("exists -> " + exists); } /** * 刪除數據 */ @Test public void testDelete() throws Exception { DeleteRequest deleteRequest = new DeleteRequest("test", "house", "4hN-OW4BpJzEX51oe-Of"); DeleteResponse response = this.client.delete(deleteRequest, RequestOptions.DEFAULT); System.out.println(response.status());// OK or NOT_FOUND } /** * 更新數據 */ @Test public void testUpdate() throws Exception { UpdateRequest updateRequest = new UpdateRequest("test", "house", "4BN4OW4BpJzEX51o3-PZ"); Map<String, Object> data = new HashMap<>(); data.put("title", "南京西路2 一室一廳2"); data.put("price", "4000"); updateRequest.doc(data); UpdateResponse response = this.client.update(updateRequest, RequestOptions.DEFAULT); System.out.println("version -> " + response.getVersion()); } /** * 查詢數據 */ @Test public void testSearch() throws Exception { SearchRequest searchRequest = new SearchRequest("test"); searchRequest.types("house"); SearchSourceBuilder sourceBuilder = new SearchSourceBuilder(); sourceBuilder.query(QueryBuilders.matchQuery("title", "拎包入住")); sourceBuilder.from(0); sourceBuilder.size(5); sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS)); searchRequest.source(sourceBuilder); SearchResponse search = this.client.search(searchRequest, RequestOptions.DEFAULT); System.out.println("搜索到->" + search.getHits().totalHits + "條數據"); SearchHits hits = search.getHits(); for (SearchHit hit : hits) { System.out.println(hit.getSourceAsString()); } } }
Spring Data項目對Elasticsearch作了支持,其目的就是簡化對Elasticsearch的操做,https://spring.io/projects/sp...。apache
1.導入依賴json
<?xml version="1.0" encoding="UTF-8"?> <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 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.2.0.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.example</groupId> <artifactId>elasticsearch</artifactId> <version>0.0.1-SNAPSHOT</version> <name>elasticsearch</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency> <dependency> <groupId>org.elasticsearch.client</groupId> <artifactId>elasticsearch-rest-client</artifactId> <version>6.5.4</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.9.4</version> </dependency> <!--REST高級客戶端--> <dependency> <groupId>org.elasticsearch.client</groupId> <artifactId>elasticsearch-rest-high-level-client</artifactId> <version>6.5.4</version> </dependency> <!--SpringBoot整合--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-elasticsearch</artifactId> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
2.編寫application.yml
spring: application: name: spring-elasticsearch data: elasticsearch: cluster-name: docker-cluster cluster-nodes: 47.101.129.45:9300
這裏要注意,使用的端口是9300,而並不是9200,緣由是9200是RESTful端口,9300是API端口。
3.編寫測試
@Data @AllArgsConstructor @NoArgsConstructor @Document(indexName = "demo", type = "person", createIndex = false) public class Person { /** * 1.索引庫(indices) indices是index的複數,表明許多的索引, * 2.類型(type) 類型是模擬mysql中的table概念,一個索引庫下能夠有不一樣類型的索引,好比商品索引,訂單索引,其數據格式不一樣。不過這會致使索引庫混亂,所以將來版本中會移除這個概念 * 3.文檔(document) 存入索引庫原始的數據。好比每一條商品信息,就是一個文檔 * 4.字段(field) 文檔中的屬性 * 5.映射配置(mappings) 字段的數據類型、屬性、是否索引、是否存儲等特性 */ /** * @Document 做用在類,標記實體類爲文檔對象,通常有兩個屬性 * 1.indexName:對應索引庫名稱 * 2.type:對應在索引庫中的類型 * 3.shards:分片數量,默認5 * 4.replicas:副本數量,默認1 * @Id 做用在成員變量,標記一個字段做爲id主鍵 * @Field 做用在成員變量,標記爲文檔的字段,並指定字段映射屬性: * 1.type:字段類型,是枚舉:FieldType,能夠是text、long、short、date、integer、object等 * 2.text:存儲數據時候,會自動分詞,並生成索引 * 3.keyword:存儲數據時候,不會分詞創建索引 * 4.Numerical:數值類型,分兩類 * 基本數據類型:long、interger、short、byte、double、float、half_float * 浮點數的高精度類型:scaled_float * 須要指定一個精度因子,好比10或100。elasticsearch會把真實值乘以這個因子後存儲,取出時再還原。 * 5.Date:日期類型 * elasticsearch能夠對日期格式化爲字符串存儲,可是建議咱們存儲爲毫秒值,存儲爲long,節省空間。 * 6.index:是否索引,布爾類型,默認是true * 7.store:是否存儲,布爾類型,默認是false * 8.analyzer:分詞器名稱,這裏的ik_max_word即便用ik分詞器 */ @Id private Long id; @Field(store = true) private String name; @Field private Integer age; @Field private String mail; @Field(store = true) private String hobby; }
1)新增數據
/** * Spring Data ElasticSearch */ @RunWith(SpringRunner.class) @SpringBootTest public class TestSpringBootES { @Autowired private ElasticsearchTemplate elasticsearchTemplate; /** * 添加數據 */ @Test public void save() { User user = new User(); user.setId(1001L); user.setName("趙柳"); user.setAge(20); user.setHobby("足球、籃球、聽音樂"); IndexQuery indexQuery = new IndexQueryBuilder() .withObject(user).build(); String index = this.elasticsearchTemplate.index(indexQuery); System.out.println(index); } }
2)批量插入
@Test public void testBulk() { List list = new ArrayList<>(); for (int i = 0; i < 5000; i++) { User person = new User(); person.setId(1001L + i); person.setAge(i % 50 + 10); person.setName("張三" + i); person.setHobby("足球、籃球、聽音樂"); IndexQuery indexQuery = new IndexQueryBuilder().withObject(person).build(); list.add(indexQuery); } Long start = System.currentTimeMillis(); this.elasticsearchTemplate.bulkIndex(list); System.out.println("用時:" + (System.currentTimeMillis() - start)); }
3)局部更新,所有更新使用index覆蓋便可
@Test public void testUpdate() { IndexRequest indexRequest = new IndexRequest(); indexRequest.source("age", "30"); UpdateQuery updateQuery = new UpdateQueryBuilder() .withId("1002") .withClass(User.class) .withIndexRequest(indexRequest).build(); UpdateResponse response = this.elasticsearchTemplate.update(updateQuery); System.out.println(response); }
4)刪除
@Test public void testDelete() { String result = this.elasticsearchTemplate.delete(User.class, "1002"); System.out.println(result); }
5)查詢
@Test public void testSearch() { PageRequest pageRequest = PageRequest.of(0, 10);//設置分頁參數 SearchQuery searchQuery = new NativeSearchQueryBuilder() .withQuery(QueryBuilders.matchQuery("name", "趙柳"))//match查詢 .withPageable(pageRequest) .build(); AggregatedPage<User> persons = this.elasticsearchTemplate.queryForPage(searchQuery, User.class); System.out.println("persons ->" + persons); System.out.println("總頁數:" + persons.getTotalPages()); //獲取總頁數 List<User> content = persons.getContent();// 獲取搜索到的數據 for (User p : content) { System.out.println(p); } }
3.編寫測試
1)建立實體Pojo
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; @Data @AllArgsConstructor @NoArgsConstructor @Document(indexName = "commodity", type = "docs", shards = 1, replicas = 0) public class Commodity { @Id private Long id; @Field(type = FieldType.Text, analyzer = "ik_max_word") private String title; //標題 @Field(type = FieldType.Keyword) private String category;// 分類 @Field(type = FieldType.Keyword) private String brand; // 品牌 @Field(type = FieldType.Double) private Double price; // 價格 @Field(index = false, type = FieldType.Keyword) private String images; // 圖片地址 }
2)繼承ElasticsearchRepository
import com.example.elasticsearch.pojo.Commodity; import org.springframework.data.elasticsearch.repository.ElasticsearchRepository; import java.util.List; public interface CommodityRepository extends ElasticsearchRepository<Commodity, Long> { }
3)測試
@RunWith(SpringRunner.class) @SpringBootTest public class TestSpringBootES2 { @Resource private CommodityRepository commodityRepository; /** * 建立索引 */ @Test public void createIndex() { boolean index = elasticsearchTemplate.createIndex(Commodity.class); System.out.println(index); } /** * 添加數據 */ @Test public void testInsert() { Commodity commodity = new Commodity(1L, "小米手機7", " 手機", "小米", 3499.00, "http://image.baidu.com/13123.jpg"); Commodity save = commodityRepository.save(commodity); System.out.println(save); } }