在ES当中其实有非常多的查询功能,本文就来通过代码案例带大家梳理下不同的查询类型的具体含义分别是什么?
本文所选用的依赖内容如下:
xml
<dependencies>
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>6.5.4</version>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>6.5.4</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.10.2</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.20</version>
<scope>provided</scope>
</dependency>
</dependencies>
Index插入操作
在进行案例讲解之前,我们首先需要创建一颗索引树,这里我们可以利用es-rest-high-level-client工具包的index函数去进行操作。
java
public static RestHighLevelClient getClient() {
HttpHost httpHost = new HttpHost("这里写自己es的地址",9200);
RestClientBuilder clientBuilder = RestClient.builder(httpHost);
RestHighLevelClient client = new RestHighLevelClient(clientBuilder);
return client;
}
java
private RestHighLevelClient client = EsClient.getClient();
private String index = "sms";
private String type = "yidong";
private ObjectMapper objectMapper = new ObjectMapper();
@Test
public void createEsData() throws IOException {
Settings.Builder setting = Settings.builder()
.put("number_of_shards", 3)
.put("number_of_replicas", 1);
SmsPO smsPO = new SmsPO();
XContentBuilder mappings = JsonXContent.contentBuilder()
.startObject()
.startObject("properties")
.startObject("mobile")
.field("type", "text")
.endObject()
.startObject("corpName")
.field("type", "text")
.endObject()
.startObject("smsContent")
.field("type", "text")
.endObject()
.startObject("state")
.field("type", "integer")
.endObject()
.startObject("operatorId")
.field("type", "integer")
.endObject()
.startObject("province")
.field("type", "text")
.endObject()
.startObject("ip")
.field("type", "text")
.endObject()
.startObject("replyTotal")
.field("type", "integer")
.endObject()
.startObject("fee")
.field("type", "integer")
.endObject()
.startObject("createTime")
.field("type", "date")
.field("format", "yyyy-mm-dd")
.endObject()
.startObject("updateTime")
.field("type", "date")
.field("format", "yyyy-mm-dd")
.endObject()
.endObject()
.endObject();
CreateIndexRequest request = new CreateIndexRequest(index)
.settings(setting)
.mapping(type, mappings);
CreateIndexResponse response = client.indices().create(request, RequestOptions.DEFAULT);
System.out.println(response);
}
@Test
public void testInsertData() throws IOException {
for (int i = 0; i < 100; i++) {
SmsPO smsPO = new SmsPO();
smsPO.setId((long) i);
smsPO.setMobile("15778293032");
smsPO.setIp("127.0.0.1");
smsPO.setFee(i + 500);
smsPO.setProvince("BeiJin");
smsPO.setOperatorId(i);
smsPO.setCreateTime(new Date());
smsPO.setUpdateTime(new Date());
String json = objectMapper.writeValueAsString(smsPO);
IndexRequest indexRequest = new IndexRequest(index, type, smsPO.getId().toString());
indexRequest.source(json, XContentType.JSON);
IndexResponse indexResponse = client.index(indexRequest, RequestOptions.DEFAULT);
System.out.println(indexResponse.getResult().toString());
}
}
上述代码可以结合自己的实际环境去修改es的地址。当你执行完创建索引和插入数据两段函数之后,可以在kibana上看到对应的数据信息:
Term查询
下边是使用term查询的代码案例:
java
@Test
public void testTermQuery() throws IOException {
SearchRequest request = new SearchRequest(index);
request.types(type);
SearchSourceBuilder builder = new SearchSourceBuilder();
builder.from(0);
builder.size(5);
builder.query(QueryBuilders.termQuery("province", "BeiJin"));
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
System.out.println(response);
}
所谓的term查询可以理解为是精确匹配查询的意思。
Match查询
来看代码案例:
java
@Test
public void testMatchQuery() throws IOException {
SearchRequest request = new SearchRequest(index);
request.types(type);
SearchSourceBuilder builder = new SearchSourceBuilder();
builder.query(QueryBuilders.matchQuery("province", "BeiJin"));
request.source(builder);
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
System.out.println(response.getHits().getHits().length);
}
其底层其实就是将关键字进行分词处理,拆解为多个组成部分,然后分别调用多次term查询进行精确匹配。
MultiMatch查询
来看代码案例:
java
@Test
public void testMultiMatchQuery() throws IOException {
SearchRequest request = new SearchRequest(index);
request.types(type);
SearchSourceBuilder builder = new SearchSourceBuilder();
//相当于是province和smsContent字段都会进行match匹配
builder.query(QueryBuilders.multiMatchQuery("BeiJin", "province", "smsContent"));
request.source(builder);
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
System.out.println(response.getHits().getHits().length);
}
使用multiMatch其实底层就是多个关键字的match查询,很好理解。
MatchAll查询
该查询的目的就是将es中的所有数据都给检索出来的意思。相关代码如下:
java
@Test
public void testMatchAllQuery() throws IOException {
SearchRequest request = new SearchRequest(index);
request.types(type);
SearchSourceBuilder builder = new SearchSourceBuilder();
//这里指定数量,如果不指定,默认最多10条
builder.size(15);
builder.query(QueryBuilders.matchAllQuery());
request.source(builder);
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
System.out.println(response.getHits().getHits().length);
}
这里可以利用size参数去指定你所需要检索的数据量。
Id检索
来看代码案例:
java
@Test
public void testIdsQuery() throws IOException {
SearchRequest request = new SearchRequest(index);
request.types(type);
SearchSourceBuilder builder = new SearchSourceBuilder();
builder.query(QueryBuilders.idsQuery().addIds("2", "3", "4"));
request.source(builder);
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
SearchHit[] result = response.getHits().getHits();
if (result.length > 0) {
for (SearchHit documentFields : result) {
System.out.println(documentFields.getSourceAsString());
}
}
}
这个就非常容易理解了,和MySQL的in查询有点类似,只不过es规定的是对主键id进行in查询。
Prefix检索
java
@Test
public void testPrefixQuery() throws IOException {
SearchRequest request = new SearchRequest(index);
request.types(type);
SearchSourceBuilder builder = new SearchSourceBuilder();
builder.query(QueryBuilders.prefixQuery("province","Bei"));
request.source(builder);
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
SearchHit[] result = response.getHits().getHits();
if (result.length > 0) {
for (SearchHit documentFields : result) {
System.out.println(documentFields.getSourceAsMap());
}
}
}
前缀检索其实看名字就很好理解出来了,类似于mysql的 where key like 'test%' 这种含义。
Fuzzy查询
代码案例如下:
java
@Test
public void testFuzzyQuery() throws IOException {
SearchRequest request = new SearchRequest(index);
request.types(type);
SearchSourceBuilder builder = new SearchSourceBuilder();
//及时出现了部分错别字,也是可以模糊识别的
builder.query(QueryBuilders.fuzzyQuery("province","Beijin"));
request.source(builder);
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
SearchHit[] result = response.getHits().getHits();
if (result.length > 0) {
for (SearchHit documentFields : result) {
System.out.println(documentFields.getSourceAsMap());
}
}
}
Fuzzy可以说是一种更为智能的模糊查询,要比MySQL的like查询强。例如我们es中存储的数据,province均为BeiJin,但是如果你所传入的参数有一些误差,礼物Beijin,Fuzzy底层是可以自动帮你兼容的。
WildCard查询
先来看代码:
java
public void testWildCardQuery() throws IOException {
SearchRequest request = new SearchRequest(index);
request.types(type);
SearchSourceBuilder builder = new SearchSourceBuilder();
builder.query(QueryBuilders.wildcardQuery("ip","127*"));
request.source(builder);
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
SearchHit[] result = response.getHits().getHits();
if (result.length > 0) {
for (SearchHit documentFields : result) {
System.out.println(documentFields.getSourceAsMap());
}
}
使用wildCard查询,是可以支持通配符功能的,也是一种比较灵活的查询方式。
Range查询
java
@Test
public void testRangeQuery() throws IOException {
SearchRequest request = new SearchRequest(index);
request.types(type);
SearchSourceBuilder builder = new SearchSourceBuilder();
//及时出现了部分错别字,也是可以模糊识别的
builder.query(QueryBuilders.rangeQuery("id").gt("95"));
request.source(builder);
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
SearchHit[] result = response.getHits().getHits();
if (result.length > 0) {
for (SearchHit documentFields : result) {
System.out.println(documentFields.getSourceAsMap());
}
}
}
range查询是一种范围查询的类型,假设我们的id是数字类型,使用range可以检索大于某个特定值的区间数据。
aggregation查询
使用aggregation是一种统计类的查询功能,来看下边这段求最大值和最小值的代码案例:
java
//获取最大值和最小值
@Test
public void testAggregationQuery() throws IOException {
SearchRequest request = new SearchRequest(index);
request.types(type);
SearchSourceBuilder builder = new SearchSourceBuilder();
builder.aggregation(AggregationBuilders.extendedStats("agg").field("id"));
request.source(builder);
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
ExtendedStats agg = response.getAggregations().get("agg");
System.out.println(agg.getMax());
System.out.println(agg.getMin());
}