spring-data-elasticsearch的模板使用(二)
这里讲述java API
这里的导包、配置yml、写实体类与上文的一样,这里忽略。
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.sinux.springdataelasticsearch.es.entity.Item;
import com.sinux.springdataelasticsearch.es.util.Result;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.action.bulk.BulkRequestBuilder;
import org.elasticsearch.action.index.IndexRequestBuilder;
import org.elasticsearch.action.search.SearchRequestBuilder;
import org.elasticsearch.action.support.WriteRequest;
import org.elasticsearch.action.update.UpdateRequestBuilder;
import org.elasticsearch.client.Client;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.elasticsearch.core.query.SearchQuery;
import org.springframework.data.web.PageableDefault;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* java API操作文档库
*/
@RestController
@RequestMapping("/esclient")
@Api(value = "es的swagger", tags = "es的client操作")
@Slf4j
public class EsClientController {
@Autowired
private ElasticsearchTemplate elasticsearchTemplate;
/**
* 往索引库添加文档信息
*/
@PostMapping("/save")
@ApiOperation(value = "往索引库添加文档信息", notes = "往索引库添加文档信息")
public <T> void save(@RequestBody T t, String index, String type) {
/**
* client.prepareIndex 参数可以是零个(其后必须使用 index(String) 和 type(String) 方法)
* 两个(client.prepareIndex(index,type))和三个(client.prepareIndex(index,type,id)),
* 其中 index 类似于库名,type 类似于表名(和前面说过的一样),而 id 则是每条记录的惟一编码。
* 通常情况下我们会把实体的唯一编码作为 es 的 id。如果不给 id 的时候,由 es 自动生成。
*/
Map<String, Object> sourceMap = ((JSONObject) JSON.toJSON(t)).getInnerMap();
Client client = elasticsearchTemplate.getClient();
if (t instanceof Item) {
Item item = (Item) t;
client.
prepareIndex(index, type, "" + item.getId()).
setSource(sourceMap, XContentType.JSON).
setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE).
get();
} else {
client.
prepareIndex(index, type).
setSource(sourceMap, XContentType.JSON).
setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE).
get();
}
}
/**
* 功能描述: 批量更新
*/
@PostMapping("/batchupdate")
@ApiOperation(value = "批量更新", notes = "批量更新")
public Result batchupdate(@RequestBody List<Item> list) {
Client client = elasticsearchTemplate.getClient();
BulkRequestBuilder requestBuilder = client.prepareBulk();
try {
list.parallelStream().forEach(es -> {
Map<String, Object> sourceMap = ((JSONObject) JSON.toJSON(es)).getInnerMap();
UpdateRequestBuilder updateRequestBuilder = client.
prepareUpdate("item", "docs", "" + es.getId()).
setDoc(sourceMap, XContentType.JSON);
if (null != updateRequestBuilder) {
requestBuilder.add(updateRequestBuilder);
}
});
requestBuilder.setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE).get();
return new Result("批量更新成功!");
} catch (Exception e) {
e.printStackTrace();
return new Result("批量更新失败!");
}
}
/**
* 功能描述: 批量保存数据
*/
@PostMapping("/batchsave")
@ApiOperation(value = "批量保存数据", notes = "批量保存数据")
public Result batchsave(@RequestBody List<Item> list) {
Client client = elasticsearchTemplate.getClient();
BulkRequestBuilder requestBuilder = client.prepareBulk();
try {
list.parallelStream().forEach(es -> {
Map<String, Object> sourceMap = ((JSONObject) JSON.toJSON(es)).getInnerMap();
IndexRequestBuilder indexRequestBuilder = client.
prepareIndex("item", "docs", "" + es.getId()).
setSource(sourceMap, XContentType.JSON);
if (null != indexRequestBuilder) {
requestBuilder.add(indexRequestBuilder);
}
requestBuilder.setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE).get();
});
return new Result("批量插入成功!");
} catch (Exception e) {
e.printStackTrace();
return new Result("插入失败!");
}
}
/***
* 根据id查询
*/
@PostMapping("/findbyid")
@ApiOperation(value = "根据id查询", notes = "根据id查询")
public Result findById(@RequestBody String id) {
log.info("……………………" + id);
List<Map<String, Object>> list = new ArrayList<>();
QueryBuilder queryBuilder = QueryBuilders.idsQuery().addIds(id);
SearchRequestBuilder index = elasticsearchTemplate.getClient().prepareSearch("item").setQuery(queryBuilder).setSize(10);
SearchHits hits = index.get().getHits();
for (SearchHit hit : hits) {
list.add(hit.getSourceAsMap());
}
log.info("=====================" + list);
return new Result(list);
}
/***
* 按指定字段模糊查询
*/
@PostMapping("/queryindexfield")
@ApiOperation(value = "按指定字段模糊查询", notes = "按指定字段模糊查询")
public Result findByField(@RequestBody String brand) {
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
//模糊匹配查询,需要以*号结尾,提高查询效率
boolQueryBuilder.must(QueryBuilders.regexpQuery("brand", ".*" + brand.toLowerCase() + ".*"));
SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(boolQueryBuilder).build();
List<Item> list = elasticsearchTemplate.queryForList(searchQuery, Item.class);
return new Result(list);
}
/**
* 批量删除
*/
@PostMapping("/batchdel")
@ApiOperation(value = "批量删除", notes = "批量删除")
public Result del(@RequestBody String ids) {
log.info("===========" + ids);
String[] id = ids.split(",");
try {
for (String Id : id) {
elasticsearchTemplate.delete(Item.class, Id);
}
return new Result("删除成功");
} catch (Exception e) {
e.printStackTrace();
return new Result("删除失败" + e.getMessage());
}
}
/**
* multi_match多个字段匹配某字符串,模糊查询
* 如果我们希望title,content两个字段去匹配某个字符串,只要任何一个字段包括该字符串即可,就可以使用multimatch
* withPageable:分页
* int start,起始页,***第一页是start为0***
* int maxSize,每页条数
* withSort:排序
* SortBuilders.fieldSort("id").order(SortOrder.DESC)是id倒序排序,如果是ASC就是升序
*/
@PostMapping("/multimatch")
@ApiOperation(value = "多个字段匹配某字符串,模糊查询", notes = "多个字段匹配某字符串,模糊查询")
public Result multimatch(@RequestBody String keyword,int start,int maxSize) {
log.info("___________________________________________");
SearchQuery searchQuery = new NativeSearchQueryBuilder().
withQuery(QueryBuilders.multiMatchQuery(keyword, "title", "category", "brand")).
withPageable(PageRequest.of(start,maxSize)).
withSort(SortBuilders.fieldSort("id").order(SortOrder.DESC)).
build();
List<Item> list = elasticsearchTemplate.queryForList(searchQuery, Item.class);
log.info("===================" + list);
return new Result(list);
}
}
总结:
matchQuery:词条匹配,先分词然后在调用termQuery进行匹配
TermQuery:词条匹配,不分词
wildcardQuery:通配符匹配
fuzzyQuery:模糊匹配
rangeQuery:范围匹配
booleanQuery:布尔查询
NativeSearchQueryBuilder:Spring提供的一个查询条件构建器,帮助构建json格式的请求体
QueryBuilders.matchQuery(“title”, “小米手机”):利用QueryBuilders来生成一个查询。QueryBuilders提供了大量的静态方法,用于生成各种不同类型的查询。
BooleanClause用于表示布尔查询子句关系的类,包括:BooleanClause.Occur.MUST,BooleanClause.Occur.MUST_NOT,BooleanClause.Occur.SHOULD。必须包含,不能包含,可以包含三种.有以下6种组合:
1.MUST和MUST:交集。
2.MUST和MUST_NOT:表示查询结果中不能包含MUST_NOT所对应得查询子句的检索结果。
3.SHOULD与MUST_NOT:连用时,功能同MUST和MUST_NOT。
4.SHOULD与MUST连用时,结果为MUST子句的检索结果,但是SHOULD可影响排序。
5.SHOULD与SHOULD:并集。
6.MUST_NOT和MUST_NOT:无意义,检索无结果。
使用QueryBuilder
* termQuery(“key”, obj) 完全匹配
* termsQuery(“key”, obj1, obj2…) 一次匹配多个值
* matchQuery(“key”, Obj) 单个匹配, field不支持通配符, 前缀具高级特性
* multiMatchQuery(“text”, “field1”, “field2”…); 匹配多个字段, field有通配符忒行
* matchAllQuery(); 匹配所有文件