Loading

ElasticSearch增删改查

ElasticSearch增删改查

1 HTTP方式

1.1 幂等
POST 不是幂等的。
GET,PUT,DELETE,HEAD,OPTIONS和TRACE是幂等。
http://restful.p2hp.com/learn/idempotent-rest-apis
https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html
https://stackoverflow.com/questions/7016785/is-put-delete-idempotent-with-rest-automatic
1.2 索引CRUD
# delete/404
DELETE index01
# search all indeces
GET _cat/indices
# get/404
GET index01
# 200/404
HEAD index01
# 第一次405 资源被禁止
POST index02
# 创建,第二次400页面不存在或者请求错误
PUT index01

GET /

1.3 文档CRUD
# 可以更新N次
POST index01/_update/1
{"doc":{}}
# 405 资源禁止
PUT index01/_update/1
{"doc":{}}
# 读取
GET index01/_doc/1
# 405 资源禁止
PUT index01/_doc
{}
# 第二次409 与服务器当前资源冲突
POST index01/_create/4
{}
# 第二次409 与服务器当前资源冲突
PUT index01/_create/3
{}
# 每次文档不一样
POST index01/_doc
{}
# 每次版本不一样
POST index01/_doc/1
{}
# 每次版本不一样
PUT index01/_doc/1
{}

2 JavaAPI方式

2.1 POM依赖
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>7.8.0</version>
</dependency>
<!-- elasticsearch的客户端 -->
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>7.8.0</version>
</dependency>
<!-- elasticsearch依赖2.x的log4j -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.8.2</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.8.2</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.9</version>
</dependency>
2.2 索引CRUD
2.2.1 创建索引
RestHighLevelClient esClient = new RestHighLevelClient(
RestClient.builder(new HttpHost("localhost", 9200, "http"))
);

// 创建索引
CreateIndexRequest request = new CreateIndexRequest("user");
CreateIndexResponse createIndexResponse =
esClient.indices().create(request, RequestOptions.DEFAULT);

// 响应状态
boolean acknowledged = createIndexResponse.isAcknowledged();
System.out.println("索引操作 :" + acknowledged);

esClient.close();
2.2.2 删除索引
RestHighLevelClient esClient = new RestHighLevelClient(
RestClient.builder(new HttpHost("localhost", 9200, "http"))
);

// 查询索引
DeleteIndexRequest request = new DeleteIndexRequest("user");

AcknowledgedResponse response = esClient.indices().delete(request, RequestOptions.DEFAULT);

// 响应状态
System.out.println(response.isAcknowledged());

esClient.close();

2.2.3 查询索引
RestHighLevelClient esClient = new RestHighLevelClient(
RestClient.builder(new HttpHost("localhost", 9200, "http"))
);

// 查询索引User
GetIndexRequest request = new GetIndexRequest("user");
// 查询所有索引
// GetIndexRequest request = new GetIndexRequest("*");

GetIndexResponse getIndexResponse =
esClient.indices().get(request, RequestOptions.DEFAULT);

// 响应状态
System.out.println(getIndexResponse.getAliases());
System.out.println(getIndexResponse.getMappings());
System.out.println(getIndexResponse.getSettings());

esClient.close();

2.3 文档CRUD
2.3.1 实体User
public class User {
private String name;
private String sex;
private Integer age;

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getSex() {
return sex;
}

public void setSex(String sex) {
this.sex = sex;
}

public Integer getAge() {
return age;
}

public void setAge(Integer age) {
this.age = age;
}
}

2.3.2 插入单条文档
RestHighLevelClient esClient = new RestHighLevelClient(
RestClient.builder(new HttpHost("localhost", 9200, "http"))
);

// 插入数据
IndexRequest request = new IndexRequest();
request.index("user").id("1001");

User user = new User();
user.setName("tom");
user.setAge(30);
user.setSex("男");

// 向ES插入数据,必须将数据转换位JSON格式
ObjectMapper mapper = new ObjectMapper();
String userJson = mapper.writeValueAsString(user);
request.source(userJson, XContentType.JSON);

IndexResponse response = esClient.index(request, RequestOptions.DEFAULT);

System.out.println(response.getResult());

esClient.close();
2.3.3 批量插入文档
RestHighLevelClient esClient = new RestHighLevelClient(
RestClient.builder(new HttpHost("localhost", 9200, "http"))
);
for (int j = 0; j < 50; j++) {
// 批量插入数据
BulkRequest request = new BulkRequest();
System.out.println(j);
System.out.println(new Date());
for (int i = 0; i < 100_000; i++) {
request.add(new IndexRequest().index("user").source(XContentType.JSON, "name", "tom" + i, "age", i * 11, "sex", "男"));
}
System.out.println(new Date());
BulkResponse response = esClient.bulk(request, RequestOptions.DEFAULT);
System.out.println(response.getTook());
System.out.println(response.getItems());
}

esClient.close();

2.3.4 获取单条文档
RestHighLevelClient esClient = new RestHighLevelClient(
RestClient.builder(new HttpHost("localhost", 9200, "http"))
);

// 查询数据
GetRequest request = new GetRequest();
request.index("user").id("1001");
GetResponse response = esClient.get(request, RequestOptions.DEFAULT);

System.out.println(response.getSourceAsString());

esClient.close();

2.3.5 更新单条数据
RestHighLevelClient esClient = new RestHighLevelClient(
RestClient.builder(new HttpHost("localhost", 9200, "http"))
);

// 修改数据
UpdateRequest request = new UpdateRequest();
request.index("user").id("1001");
request.doc(XContentType.JSON, "sex", "女");

UpdateResponse response = esClient.update(request, RequestOptions.DEFAULT);

System.out.println(response.getResult());

esClient.close();

2.3.6 删除单条数据
RestHighLevelClient esClient = new RestHighLevelClient(
RestClient.builder(new HttpHost("localhost", 9200, "http"))
);


DeleteRequest request = new DeleteRequest();
request.index("user").id("1001");

DeleteResponse response = esClient.delete(request, RequestOptions.DEFAULT);
System.out.println(response.toString());

esClient.close();

2.3.7 批量删除数据
RestHighLevelClient esClient = new RestHighLevelClient(
RestClient.builder(new HttpHost("localhost", 9200, "http"))
);

// 批量删除数据
BulkRequest request = new BulkRequest();

request.add(new DeleteRequest().index("user").id("1001"));
request.add(new DeleteRequest().index("user").id("1002"));
request.add(new DeleteRequest().index("user").id("1003"));

BulkResponse response = esClient.bulk(request, RequestOptions.DEFAULT);
System.out.println(response.getTook());
System.out.println(response.getItems());

esClient.close();

2.3.8 查询所有
RestHighLevelClient esClient = new RestHighLevelClient(
RestClient.builder(new HttpHost("localhost", 9200, "http"))
);

// 1. 查询索引的所有数据
SearchRequest request = new SearchRequest();
request.indices("user");

// 构造查询条件
SearchSourceBuilder builder = new SearchSourceBuilder();
builder.query(QueryBuilders.matchAllQuery());

request.source(builder);

SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);

SearchHits hits = response.getHits();

System.out.println(response.getTook());
System.out.println(hits.getTotalHits());
Iterator<SearchHit> iterator = hits.iterator();
while (iterator.hasNext()) {
SearchHit hit = iterator.next();
System.out.println(hit.getSourceAsString());
}

esClient.close();

2.3.9 组合查询
RestHighLevelClient esClient = new RestHighLevelClient(
RestClient.builder(new HttpHost("localhost", 9200, "http"))
);

// 1. 查询索引中全部的数据
// SearchRequest request = new SearchRequest();
// request.indices("user");
//
// request.source(new SearchSourceBuilder().query(QueryBuilders.matchAllQuery()));
//
// SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);
//
// SearchHits hits = response.getHits();
//
// System.out.println(hits.getTotalHits());
// System.out.println(response.getTook());
//
// for ( SearchHit hit : hits ) {
// System.out.println(hit.getSourceAsString());
// }

// 2. 条件查询 : termQuery
// SearchRequest request = new SearchRequest();
// request.indices("user");
//
// request.source(new SearchSourceBuilder().query(QueryBuilders.termQuery("age", 30)));
// SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);
//
// SearchHits hits = response.getHits();
//
// System.out.println(hits.getTotalHits());
// System.out.println(response.getTook());
//
// for ( SearchHit hit : hits ) {
// System.out.println(hit.getSourceAsString());
// }

// 3. 分页查询
// SearchRequest request = new SearchRequest();
// request.indices("user");
//
// SearchSourceBuilder builder = new SearchSourceBuilder().query(QueryBuilders.matchAllQuery());
// // (当前页码-1)*每页显示数据条数
// builder.from(2);
// builder.size(2);
// request.source(builder);
// SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);
//
// SearchHits hits = response.getHits();
//
// System.out.println(hits.getTotalHits());
// System.out.println(response.getTook());
//
// for ( SearchHit hit : hits ) {
// System.out.println(hit.getSourceAsString());
// }

// // 4. 查询排序
// SearchRequest request = new SearchRequest();
// request.indices("user");
//
// SearchSourceBuilder builder = new SearchSourceBuilder().query(QueryBuilders.matchAllQuery());
// //
// builder.sort("age", SortOrder.DESC);
//
// request.source(builder);
// SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);
//
// SearchHits hits = response.getHits();
//
// System.out.println(hits.getTotalHits());
// System.out.println(response.getTook());
//
// for ( SearchHit hit : hits ) {
// System.out.println(hit.getSourceAsString());
// }

// // 5. 过滤字段
// SearchRequest request = new SearchRequest();
// request.indices("user");
//
// SearchSourceBuilder builder = new SearchSourceBuilder().query(QueryBuilders.matchAllQuery());
// //
// String[] excludes = {"age"};
// String[] includes = {};
// builder.fetchSource(includes, excludes);
//
// request.source(builder);
// SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);
//
// SearchHits hits = response.getHits();
//
// System.out.println(hits.getTotalHits());
// System.out.println(response.getTook());
//
// for ( SearchHit hit : hits ) {
// System.out.println(hit.getSourceAsString());
// }

// // 6. 组合查询
// SearchRequest request = new SearchRequest();
// request.indices("user");
//
// SearchSourceBuilder builder = new SearchSourceBuilder();
// BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
//
// //boolQueryBuilder.must(QueryBuilders.matchQuery("age", 30));
// //boolQueryBuilder.must(QueryBuilders.matchQuery("sex", "男"));
// //boolQueryBuilder.mustNot(QueryBuilders.matchQuery("sex", "男"));
// boolQueryBuilder.should(QueryBuilders.matchQuery("age", 30));
// boolQueryBuilder.should(QueryBuilders.matchQuery("age", 40));
//
// builder.query(boolQueryBuilder);
//
// request.source(builder);
// SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);
//
// SearchHits hits = response.getHits();
//
// System.out.println(hits.getTotalHits());
// System.out.println(response.getTook());
//
// for ( SearchHit hit : hits ) {
// System.out.println(hit.getSourceAsString());
// }

// // 7. 范围查询
// SearchRequest request = new SearchRequest();
// request.indices("user");
//
// SearchSourceBuilder builder = new SearchSourceBuilder();
// RangeQueryBuilder rangeQuery = QueryBuilders.rangeQuery("age");
//
// rangeQuery.gte(30);
// rangeQuery.lt(50);
//
// builder.query(rangeQuery);
//
// request.source(builder);
// SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);
//
// SearchHits hits = response.getHits();
//
// System.out.println(hits.getTotalHits());
// System.out.println(response.getTook());
//
// for ( SearchHit hit : hits ) {
// System.out.println(hit.getSourceAsString());
// }

// 8. 模糊查询
// SearchRequest request = new SearchRequest();
// request.indices("user");
//
// SearchSourceBuilder builder = new SearchSourceBuilder();
// builder.query(QueryBuilders.fuzzyQuery("name", "wangwu").fuzziness(Fuzziness.TWO));
//
// request.source(builder);
// SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);
//
// SearchHits hits = response.getHits();
//
// System.out.println(hits.getTotalHits());
// System.out.println(response.getTook());
//
// for ( SearchHit hit : hits ) {
// System.out.println(hit.getSourceAsString());
// }

// // 9. 高亮查询
// SearchRequest request = new SearchRequest();
// request.indices("user");
//
// SearchSourceBuilder builder = new SearchSourceBuilder();
// TermsQueryBuilder termsQueryBuilder = QueryBuilders.termsQuery("name", "zhangsan");
//
// HighlightBuilder highlightBuilder = new HighlightBuilder();
// highlightBuilder.preTags("<font color='red'>");
// highlightBuilder.postTags("</font>");
// highlightBuilder.field("name");
//
// builder.highlighter(highlightBuilder);
// builder.query(termsQueryBuilder);
//
// request.source(builder);
// SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);
//
// SearchHits hits = response.getHits();
//
// System.out.println(hits.getTotalHits());
// System.out.println(response.getTook());
//
// for ( SearchHit hit : hits ) {
// System.out.println(hit.getSourceAsString());
// }

// // 10. 聚合查询
// SearchRequest request = new SearchRequest();
// request.indices("user");
//
// SearchSourceBuilder builder = new SearchSourceBuilder();
//
// AggregationBuilder aggregationBuilder = AggregationBuilders.max("maxAge").field("age");
// builder.aggregation(aggregationBuilder);
//
// request.source(builder);
// SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);
//
// SearchHits hits = response.getHits();
//
// System.out.println(hits.getTotalHits());
// System.out.println(response.getTook());
//
// for ( SearchHit hit : hits ) {
// System.out.println(hit.getSourceAsString());
// }

// 11. 分组查询
SearchRequest request = new SearchRequest();
request.indices("user");

SearchSourceBuilder builder = new SearchSourceBuilder();

AggregationBuilder aggregationBuilder = AggregationBuilders.terms("ageGroup").field("age");
builder.aggregation(aggregationBuilder);

request.source(builder);
SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);

SearchHits hits = response.getHits();

System.out.println(hits.getTotalHits());
System.out.println(response.getTook());

for ( SearchHit hit : hits ) {
System.out.println(hit.getSourceAsString());
}

 

esClient.close();

3 SpringData方式

3.1 POM依赖
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-test</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
</dependency>
</dependencies>

3.2 application.properties
# es服务地址
elasticsearch.host=127.0.0.1
# es服务端口
elasticsearch.port=9200

3.3 配置类
@ConfigurationProperties(prefix = "elasticsearch")
@Configuration
@Data
public class ElasticsearchConfig extends AbstractElasticsearchConfiguration {
private String host ;
private Integer port ;

//重写父类方法
@Override
public RestHighLevelClient elasticsearchClient() {
RestClientBuilder builder = RestClient.builder(new HttpHost(host, port));
RestHighLevelClient restHighLevelClient = new RestHighLevelClient(builder);
return restHighLevelClient;
}
}

3.4 实体类

@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
@Document(indexName = "product", shards = 3, replicas = 1)
public class Product {
@Id
private Long id;//商品唯一标识
@Field(type = FieldType.Text)
private String title;//商品名称
@Field(type = FieldType.Keyword)
private String category;//分类名称
@Field(type = FieldType.Double)
private Double price;//商品价格
@Field(type = FieldType.Keyword, index = false)
private String images;//图片地址
}

3.5 实体类DAO
@Repository
public interface ProductDao extends ElasticsearchRepository<Product, Long> {

List<Product> findByPriceBetween(double p1, double p2);
}


3.6 索引操作
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringDataESIndexTest {
@Autowired
private ElasticsearchRestTemplate elasticsearchRestTemplate;

//创建索引并增加映射配置
@Test
public void createIndex(){

boolean exists = elasticsearchRestTemplate.indexOps(Product.class).exists();
System.out.println(exists);
if (!exists) {
boolean created = elasticsearchRestTemplate.indexOps(Product.class).create();
System.out.println(created);
}
System.out.println("创建索引");
}

@Test
public void deleteIndex(){
boolean delete = elasticsearchRestTemplate.indexOps(Product.class).delete();
System.out.println(delete);

}

}

3.7 文档操作


@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringDataESProductDaoTest {
@Autowired
private ProductDao productDao;

/**
* 新增
*/
@Test
public void save() {
Product product = new Product();
product.setId(1L);
product.setTitle("华为手机");
product.setCategory("手机");
product.setPrice(2999.0);
productDao.save(product);
}

//修改
@Test
public void update() {
Product product = new Product();
product.setId(1L);
product.setTitle("小米2手机");
product.setCategory("手机");
product.setPrice(9999.0);
productDao.save(product);
}

//根据id查询
@Test
public void findById() {
Product product = productDao.findById(1L).get();
System.out.println(product);
}

//查询所有
@Test
public void findAll() {
Iterable<Product> products = productDao.findAll();
for (Product product : products) {
System.out.println(product);
}
}

//删除
@Test
public void delete() {
Product product = new Product();
product.setId(1L);
productDao.delete(product);
}

//批量新增
@Test
public void saveAll() {
List<Product> productList = new ArrayList<>();
for (int i = 0; i < 10; i++) {
productList.add(new Product((long) i, "电视" + i, "电视", 100.0 * i, ""));
productList.add(new Product(i * 20L, "手机" + i, "手机", 200.0 * i, ""));
}
productDao.saveAll(productList);
}

//分页查询
@Test
public void findByPageable() {
//设置排序(排序方式,正序还是倒序,排序的id)
Sort sort = Sort.by(Sort.Direction.DESC, "id");
int currentPage = 0;//当前页,第一页从0开始,1表示第二页
int pageSize = 5;//每页显示多少条
//设置查询分页
PageRequest pageRequest = PageRequest.of(currentPage, pageSize, sort);
//分页查询
Page<Product> productPage = productDao.findAll(pageRequest);
for (Product Product : productPage.getContent()) {
System.out.println(Product);
}
}


}

3.8 查询操作

@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringDataESSearchTest {
@Autowired
private ProductDao productDao;
@Autowired
private ElasticsearchRestTemplate elasticsearchRestTemplate;

/**
* term查询
* search(termQueryBuilder) 调用搜索方法,参数查询构建器对象
*/
@Test
public void termQuery() {

// QueryStringQueryBuilder queryStringQueryBuilder = QueryBuilders.queryStringQuery("手机");
// Query searchQuery = new NativeSearchQuery(queryStringQueryBuilder);

TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("category", "手机");
Query searchQuery = new NativeSearchQuery(termQueryBuilder);

SearchHits<Product> search = elasticsearchRestTemplate.search(searchQuery, Product.class);
for (SearchHit<Product> searchHit : search) {
System.out.println(searchHit);
}

}

/**
* term查询加分页
*/
@Test
public void termQueryByPage() {
int currentPage = 0;
int pageSize = 5;
//设置查询分页
PageRequest pageRequest = PageRequest.of(currentPage, pageSize);
TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("category", "手机");
NativeSearchQuery nativeSearchQuery = new NativeSearchQuery(termQueryBuilder);
nativeSearchQuery.setPageable(pageRequest);

// 排序
nativeSearchQuery.addSort(Sort.by(Sort.Direction.DESC, "price"));

SearchHits<Product> search = elasticsearchRestTemplate.search(nativeSearchQuery, Product.class);
for (SearchHit<Product> productSearchHit : search) {
System.out.println(productSearchHit);
}

}

/**
* 自定义查询
*/
@Test
public void findByPriceBetween() {
List<Product> byPriceBetween = productDao.findByPriceBetween(1999, 2005);
for (Product product : byPriceBetween) {
System.out.println(product);
}
}

@Test
public void testAgg() {
NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
// 不查询任何结果
queryBuilder.withSourceFilter(new FetchSourceFilter(new String[]{""}, null));
// 1、添加一个新的聚合,聚合类型为terms,聚合名称为brands,聚合字段为brand
queryBuilder.addAggregation(
AggregationBuilders.terms("cats").field("category"));

SearchHits<Product> search = elasticsearchRestTemplate.search(queryBuilder.build(), Product.class);

Aggregations aggregations = search.getAggregations();

Aggregation cats = aggregations.get("cats");
ParsedStringTerms agg = (ParsedStringTerms)cats;
// 获取桶
List<? extends Terms.Bucket> buckets = agg.getBuckets();
// 遍历
for (Terms.Bucket bucket : buckets) {
// 获取桶中的key
System.out.println(bucket.getKeyAsString());
// 获取桶中的文档数量
System.out.println(bucket.getDocCount());
}

}

}

4 参考文献
https://www.bilibili.com/video/BV1hh411D7sb

 

posted @ 2022-02-27 14:23  stono  阅读(267)  评论(0编辑  收藏  举报