Elasticsearch学习(四) - 查询①


title: Elasticsearch学习(四)-查询①
date: 2020-10-29
tags:

  • Elasticsearch
  • Elasticsearch学习(四)-查询①
    categories:
  • Elasticsearch
  • Elasticsearch学习(四)-查询①

一、准备数据

1.1 数据结构

  • Index: sms-logs-index
  • type:sms-logs-type
字段名称备注
createDate创建时间String
sendDate发送时间 date
longCode发送长号码 如 16092389287811 string
Mobile如 13000000000
corpName发送公司名称,需要分词检索
smsContent下发短信内容,需要分词检索
State短信下发状态 0 成功 1 失败 integer
Operatorid运营商编号1移动2联通3电信 integer
Province省份
ipAddr下发服务器IP地址
replyTotal短信状态报告返回时长 integer
Fee扣费 integer

1.2 创建SmsLogs实体类

@Data
@NoArgsConstructor
@AllArgsConstructor
public class SmsLogs {
    private Integer id;
    private Date createDate;
    private Date sendDate;
    private String longCode;
    private String mobile;
    private String corpName;
    private String smsContent;
    private Integer state;
    private Integer operatorId;
    private String province;
    private String ipAddr;
    private Integer replyTotal;
    private Integer fee;

}

1.3 创建索引和添加数据

public class testData {
    ObjectMapper mapper = new ObjectMapper();
    RestHighLevelClient client =  ESClient.getClient();
    String index = "sms-logs-index";
    String type="sms-logs-type";

    @Test
    public void createIndex() throws  Exception{
        // 1.准备关于索引的setting
        Settings.Builder settings = Settings.builder()
                .put("number_of_shards", 3)
                .put("number_of_replicas", 1);

        // 2.准备关于索引的mapping
        XContentBuilder mappings = JsonXContent.contentBuilder()
                .startObject()
                .startObject("properties")
                .startObject("corpName")
                .field("type", "keyword")
                .endObject()
                .startObject("createDate")
                .field("type", "date")
                .field("format", "yyyy-MM-dd")
                .endObject()
                .startObject("fee")
                .field("type", "long")
                .endObject()
                .startObject("ipAddr")
                .field("type", "ip")
                .endObject()
                .startObject("longCode")
                .field("type", "keyword")
                .endObject()
                .startObject("mobile")
                .field("type", "keyword")
                .endObject()
                .startObject("operatorId")
                .field("type", "integer")
                .endObject()
                .startObject("province")
                .field("type", "keyword")
                .endObject()
                .startObject("replyTotal")
                .field("type", "integer")
                .endObject()
                .startObject("sendDate")
                .field("type", "date")
                .field("format", "yyyy-MM-dd")
                .endObject()
                .startObject("smsContent")
                .field("type", "text")
                .field("analyzer", "ik_max_word")
                .endObject()
                .startObject("state")
                .field("type", "integer")
                .endObject()
                .endObject()
                .endObject();
        // 3.将settings和mappings 封装到到一个Request对象中
        CreateIndexRequest request = new CreateIndexRequest(index)
                .settings(settings)
                .mapping(type,mappings);
        // 4.使用client 去连接ES
        CreateIndexResponse response = client.indices().create(request, RequestOptions.DEFAULT);

        System.out.println("response:"+response.toString());

    }

    @Test
    public void  bulkCreateDoc() throws  Exception{
        // 1.准备多个json 对象
        String longcode = "1008687";
        String mobile ="138340658";
        List<String> companies = new ArrayList<>();
        companies.add("腾讯课堂");
        companies.add("阿里旺旺");
        companies.add("海尔电器");
        companies.add("海尔智家公司");
        companies.add("格力汽车");
        companies.add("苏宁易购");
        List<String> provinces = new ArrayList<>();
        provinces.add("北京");
        provinces.add("重庆");
        provinces.add("上海");
        provinces.add("晋城");
        List<String> smsContent = new ArrayList<>();
        smsContent.add("【腾讯课堂】亲爱的灯先生,您的腾讯课堂已经购买");
        smsContent.add("【阿里旺旺】亲爱的王先生,您的阿里旺旺已经购买");
        smsContent.add("【海尔电器】亲爱的李先生,您的海尔电器已经购买");
        smsContent.add("【海尔智家公司】亲爱的张先生,您的海尔智家公司已经购买");
        smsContent.add("【格力汽车】亲爱的周先生,您的格力汽车已经购买");
        smsContent.add("【苏宁易购】亲爱的赵先生,您的苏宁易购已经购买");


        BulkRequest bulkRequest = new BulkRequest();
        for (int i = 1; i <16 ; i++) {
            Thread.sleep(1000);
            SmsLogs s1 = new SmsLogs();
            s1.setId(i);
            s1.setCreateDate(new Date());
            s1.setSendDate(new Date());
            s1.setLongCode(longcode+i);
            s1.setMobile(mobile+2*i);
            s1.setCorpName(companies.get(i%5));
            s1.setSmsContent(smsContent.get(i%5));
            s1.setState(i%2);
            s1.setOperatorId(i%3);
            s1.setProvince(provinces.get(i%4));
            s1.setIpAddr("127.0.0."+i);
            s1.setReplyTotal(i*3);
            s1.setFee(i*6);
            String json1  = mapper.writeValueAsString(s1);
            bulkRequest.add(new IndexRequest(index,type,s1.getId().toString()).source(json1, XContentType.JSON));
            System.out.println("数据"+i+s1.toString());
        }

        // 3.client 执行
        BulkResponse responses = client.bulk(bulkRequest, RequestOptions.DEFAULT);

        // 4.输出结果
        System.out.println(responses.getItems().toString());
    }

}

二、ElasticSearch的各种查询

2.1 term&terms查询

2.1.1 term查询

term的查询是代表完全匹配,搜索之前不会对你搜索的关键字进行分词,对你的关键字去文档分词库中去匹
配内容

POST /sms-logs-index/sms-logs-type/_search
{
  "from": 0, # limit
  "size": 5, # page
  "query": {
    "term": {
      "province": {
        "value": "北京"
      } 
    }
  }
}

java实现方式

public class Demo4term {
    ObjectMapper mapper = new ObjectMapper();
    RestHighLevelClient client =  ESClient.getClient();
    String index = "sms-logs-index";
    String type="sms-logs-type";

    @Test
    public void termQuery() throws IOException {
        //1.创建request对象
        SearchRequest request = new SearchRequest(index);
        request.types(type);

        //2.指定查询条件
        SearchSourceBuilder builder = new SearchSourceBuilder();
        builder.from(0);
        builder.size(5);
        builder.query(QueryBuilders.termQuery("province","北京"));

        request.source(builder);

        //3.执行查询
        SearchResponse resp = client.search(request, RequestOptions.DEFAULT);

        //4.获取到_source中的数据,并展示
        for (SearchHit hit : resp.getHits().getHits()) {
            Map<String, Object> result = hit.getSourceAsMap();
            System.out.println(result);
        }
    }
2.1.2 terms查询

terms和term的查询机制是一样,都不会将指定的查询关键字进行分词,直接去分词库中匹配,找到相应文档
内容。

terms是在针对一个字段包含多个值的时候使用。

term: where province=北京

terms: where province=北京 or province= ? or province = ?

POST /sms-logs-index/sms-logs-type/_search
{
  "query": {
    "terms": {
      "province": [
        "北京",
        "上海"
      ]
    }
  }
}

java实现方式

@Test
public void termsQuery() throws IOException {
    //1.创建request
    SearchRequest request = new SearchRequest(index);
    request.types(type);

    //2.封装查询条件
    SearchSourceBuilder builder = new SearchSourceBuilder();
    builder.query(QueryBuilders.termsQuery("province","北京","上海"));

    request.source(builder);

    //3.执行查询
    SearchResponse resp = client.search(request, RequestOptions.DEFAULT);

    //4.输出_source
    for (SearchHit hit : resp.getHits().getHits()) {
        Map<String, Object> result = hit.getSourceAsMap();
        System.out.println(result);
    }
}

2.2 match查询

2.2.1 match_all查询

match 查询属于高级查询,会根据你查询字段的类型不一样,采用不同的查询方式

  • 查询的是日期或者数值,他会将你基于字符串的查询内容转换为日期或数值对待
  • 如果查询的内容是一个不能被分词的内容(keyword),match 不会将你指定的关键字进行分词
  • 如果查询的内容是一个可以被分词的内容(text),match 查询会将你指定的内容根据一定的方式进行分词,去分词库中匹配指定的内容

match 查询,实际底层就是多个term 查询,将多个term查询的结果给你封装到一起

# math_all查询
POST /sms-logs-index/sms-logs-type/_search
{
  "query": {
    "match_all": {}
  }
}

java实现方式

public class Demo5match {
    ObjectMapper mapper = new ObjectMapper();
    RestHighLevelClient client =  ESClient.getClient();
    String index = "sms-logs-index";
    String type="sms-logs-type";

    @Test
    public void matchAllQuery() throws IOException {
        //1.创建request
        SearchRequest request = new SearchRequest(index);
        request.types(type);

        //2.封装查询条件
        SearchSourceBuilder builder = new SearchSourceBuilder();
        builder.query(QueryBuilders.matchAllQuery());
        builder.size(20);       //ES默认只查询10条数据,如果想查询更多,添加size

        request.source(builder);

        //3.执行查询
        SearchResponse resp = client.search(request, RequestOptions.DEFAULT);

        //4.输出_source
        for (SearchHit hit : resp.getHits().getHits()) {
            Map<String, Object> result = hit.getSourceAsMap();
            System.out.println(result);
        }
    }
}
2.2.2 match查询

指定一个Field作为筛选的条件

# math查询
POST /sms-logs-index/sms-logs-type/_search
{
  "query": {
    "match": {
      "smsContent": "海尔电器"
    }
  }
}

java实现方式

@Test
public void matchQuery() throws IOException {
    //1.创建request
    SearchRequest request = new SearchRequest(index);
    request.types(type);

    //2.封装查询条件
    SearchSourceBuilder builder = new SearchSourceBuilder();
    //---------------------------------
    builder.query(QueryBuilders.matchQuery("smsContent","海尔电器"));
    builder.size(20);       //ES默认只查询10条数据,如果想查询更多,添加size

    //---------------------------------
    request.source(builder);

    //3.执行查询
    SearchResponse resp = client.search(request, RequestOptions.DEFAULT);

    //4.输出_source
    for (SearchHit hit : resp.getHits().getHits()) {
        Map<String, Object> result = hit.getSourceAsMap();
        System.out.println(result);
    }
}
2.2.3布尔match查询

基于一个Field匹配的内容,采用and或者or的方式连接

# 布尔math查询
POST /sms-logs-index/sms-logs-type/_search
{
  "query": {
    "match": {
      "smsContent": {
        "query": "海尔 公司",
        "operator": "or"
      }
    }
  }
}

# 布尔math查询
POST /sms-logs-index/sms-logs-type/_search
{
  "query": {
    "match": {
      "smsContent": {
        "query": "海尔 公司",
        "operator": "and"
      }
    }
  }
}

java操作

@Test
public void bollMatchQuery() throws IOException {
    //1.创建request
    SearchRequest request = new SearchRequest(index);
    request.types(type);

    //2.封装查询条件
    SearchSourceBuilder builder = new SearchSourceBuilder();

    //---------------------------------
    builder.query(QueryBuilders.matchQuery("smsContent","海尔公司").operator(Operator.AND));

    //---------------------------------
    request.source(builder);

    //3.执行查询
    SearchResponse resp = client.search(request, RequestOptions.DEFAULT);

    //4.输出_source
    for (SearchHit hit : resp.getHits().getHits()) {
        Map<String, Object> result = hit.getSourceAsMap();
        System.out.println(result);
    }
}
2.2.4 multi_match查询

match针对一个field做检索, multi_match针对多个fied进行检索,多个field对应一个text

# multi_math查询
POST /sms-logs-index/sms-logs-type/_search
{
  "query": {
    "multi_match": {
      "query": "北京",
      "fields": ["province","smsContent"]
    }
  }
}

java操作

@Test
public void multiMatchQuery() throws IOException {
    //1.创建request
    SearchRequest request = new SearchRequest(index);
    request.types(type);

    //2.封装查询条件
    SearchSourceBuilder builder = new SearchSourceBuilder();

    //---------------------------------
    builder.query(QueryBuilders.multiMatchQuery("北京","province","smsContent"));

    //---------------------------------
    request.source(builder);

    //3.执行查询
    SearchResponse resp = client.search(request, RequestOptions.DEFAULT);

    //4.输出_source
    for (SearchHit hit : resp.getHits().getHits()) {
        Map<String, Object> result = hit.getSourceAsMap();
        System.out.println(result);
    }
}

2.3 其他查询

2.3.1 id查询
# multi_math查询
GET /sms-logs-index/sms-logs-type/1

java实现方式

public class Demo6id {
    ObjectMapper mapper = new ObjectMapper();
    RestHighLevelClient client =  ESClient.getClient();
    String index = "sms-logs-index";
    String type="sms-logs-type";

    @Test
    public void findById() throws IOException {
        //1.创建request
        GetRequest request = new GetRequest(index, type, "1");

        //2.执行查询
        GetResponse resp = client.get(request, RequestOptions.DEFAULT);

        //3.输出_source
        System.out.println(resp.getSourceAsMap());
    }
}
2.3.2 ids查询

根据多个id查询,类似MsQL中的 where id in (id1,id2,id2…)

# ids查询
POST /sms-logs-index/sms-logs-type/_search
{
  "query": {
    "ids": {
      "values": ["1","2","3"]
    }
  }
}

java实现方式

@Test
public void findByIds() throws IOException {
    //1.创建request
    SearchRequest request = new SearchRequest(index);
    request.types(type);

    //2.封装查询条件
    SearchSourceBuilder builder = new SearchSourceBuilder();
    //------------------------------
    builder.query(QueryBuilders.idsQuery().addIds("1","2","3"));

    //-------------------------------
    request.source(builder);

    //3.执行查询
    SearchResponse resp = client.search(request, RequestOptions.DEFAULT);

    //4.输出_source
    for (SearchHit hit : resp.getHits().getHits()) {
        Map<String, Object> result = hit.getSourceAsMap();
        System.out.println(result);
    }
}
2.3.3 prefix查询

前缀查询,可以通过一个关键字去指定一个field 的前缀,从而查询到指定文档

# prefix查询
POST /sms-logs-index/sms-logs-type/_search
{
  "query": {
    "prefix": {
      "corpName": {
        "value": "海"
      }
    }
  }
}

java实现方式

 @Test
public void findByPrefix() throws IOException {
    //1.创建request
    SearchRequest request = new SearchRequest(index);
    request.types(type);

    //2.封装查询条件
    SearchSourceBuilder builder = new SearchSourceBuilder();
    //------------------------------
    builder.query(QueryBuilders.prefixQuery("corpName","海"));

    //-------------------------------
    request.source(builder);

    //3.执行查询
    SearchResponse resp = client.search(request, RequestOptions.DEFAULT);

    //4.输出_source
    for (SearchHit hit : resp.getHits().getHits()) {
        Map<String, Object> result = hit.getSourceAsMap();
        System.out.println(result);
    }
}
2.3.4 fuzzy查询

模糊查询,我们可以输入一个字符的大概,ES 可以根据输入的大概去匹配内容。查询结果不稳定

# fuzzy查询
POST /sms-logs-index/sms-logs-type/_search
{
  "query": {
    "fuzzy": {
      "corpName": {
        "value": "海尔电气", 
        "prefix_length": 2
      }
    }
  }
}

java操作

@Test
public void findByFuzzy() throws IOException {
    //1.创建request
    SearchRequest request = new SearchRequest(index);
    request.types(type);

    //2.封装查询条件
    SearchSourceBuilder builder = new SearchSourceBuilder();
    //------------------------------
    builder.query(QueryBuilders.fuzzyQuery("corpName","海尔电气").prefixLength(2));

    //-------------------------------
    request.source(builder);

    //3.执行查询
    SearchResponse resp = client.search(request, RequestOptions.DEFAULT);

    //4.输出_source
    for (SearchHit hit : resp.getHits().getHits()) {
        Map<String, Object> result = hit.getSourceAsMap();
        System.out.println(result);
    }
}
2.3.5 wildcard查询

通配查询,同mysql中的like 是一样的,可以在查询时,在字符串中指定通配符*和占位符?

# fuzzy查询*
POST /sms-logs-index/sms-logs-type/_search
{
  "query": {
    "wildcard": {
      "corpName": {
        "value": "腾讯*"
      }
    }
  }
}
# fuzzy查询?
POST /sms-logs-index/sms-logs-type/_search
{
  "query": {
    "wildcard": {
      "corpName": {
        "value": "腾讯??"
      }
    }
  }
}

java操作

@Test
public void findByWildcard() throws IOException {
    //1.创建request
    SearchRequest request = new SearchRequest(index);
    request.types(type);

    //2.封装查询条件
    SearchSourceBuilder builder = new SearchSourceBuilder();
    //------------------------------
    builder.query(QueryBuilders.wildcardQuery("corpName","腾讯*"));

    //-------------------------------
    request.source(builder);

    //3.执行查询
    SearchResponse resp = client.search(request, RequestOptions.DEFAULT);

    //4.输出_source
    for (SearchHit hit : resp.getHits().getHits()) {
        Map<String, Object> result = hit.getSourceAsMap();
        System.out.println(result);
    }
}
2.3.6 range查询

范围查询,只针对数值类型,对一个Field 进行大于或者小于的范围指定

  • lte:小于等于(less than)
  • lt:小于
  • gte:大于等于(greater than)
  • gt:大于
# range查询
POST /sms-logs-index/sms-logs-type/_search
{
  "query": {
    "range": {
      "fee": {
        "gt": 10, # e代表=
        "lte": 20
      }
    }
  }
}

java实现方式

@Test
public void findByRange() throws IOException {
    //1.创建request
    SearchRequest request = new SearchRequest(index);
    request.types(type);

    //2.封装查询条件
    SearchSourceBuilder builder = new SearchSourceBuilder();
    //------------------------------
    builder.query(QueryBuilders.rangeQuery("fee").gt(10).lte(20));

    //-------------------------------
    request.source(builder);

    //3.执行查询
    SearchResponse resp = client.search(request, RequestOptions.DEFAULT);

    //4.输出_source
    for (SearchHit hit : resp.getHits().getHits()) {
        Map<String, Object> result = hit.getSourceAsMap();
        System.out.println(result);
    }
}
2.3.7 regexp查询

正则查询,通过你编写的正则表达式去匹配内容

Ps:prefix wildcard fuzzy 和regexp 查询效率比较低 ,在要求效率比较高时,避免使用

# regexp查询
POST /sms-logs-index/sms-logs-type/_search
{
  "query": {
    "regexp": {
      "mobile": "138[0-9]{8}"
    }
  }
}

java实现方式

@Test
public void findByRegexp() throws IOException {
    //1.创建request
    SearchRequest request = new SearchRequest(index);
    request.types(type);

    //2.封装查询条件
    SearchSourceBuilder builder = new SearchSourceBuilder();
    //------------------------------
    builder.query(QueryBuilders.regexpQuery("mobile","138[0-9]{8}"));

    //-------------------------------
    request.source(builder);

    //3.执行查询
    SearchResponse resp = client.search(request, RequestOptions.DEFAULT);

    //4.输出_source
    for (SearchHit hit : resp.getHits().getHits()) {
        Map<String, Object> result = hit.getSourceAsMap();
        System.out.println(result);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值