ElasticSearch入门

1. Restful风格请求

REST表示资源状态转换,即请求的资源是有状态的,而状态会根据一些原则进行改变和转换。HTTP协议就遵循了REST风格,比如http://localhost:9200/test/test.txt,就表示一个资源,这个路径中不应该包含对资源的操作,对资源的操作由请求的方法表示,比如GET,POST,PUT等。其中**GET,PUT,HEAD,DELETE请求是幂等性的**,即无论对资源操作了多少次,结果都是一样的,但是POST请求不是幂等性的。

2. 倒排索引

ElasticSearch是面向文档型的数据库,一条数据就是一个文档。将ElasticSearch与MySQL中的一些概念进行类比:

但是type类型这个概念逐渐淡化了,可以忽略。 ElasticSearch能够实现快速检索文档,是因为其使用了倒排索引。首先说明正排索引(或者说正向索引),即根据文档id关联文档内容,可以根据文档id查询出文档内容,与一般的数据库类似。而倒排索引则是将文档内容的一些分词与文档id进行关联,因此可以通过关键字搜索出文档id。

3. Postman操作ElasticSearch

1)创建索引(类似于创建数据库):

PUT http://127.0.0.1:9200/shopping

其中shopping是索引名称

2)查询索引

GET http://127.0.0.1:9200/shopping

  1. 查询所有索引

GET http://127.0.0.1:9200/_cat/indices?v

  1. 删除索引

DELETE http://127.0.0.1:9200/shopping

  1. 创建文档/添加数据

POST http://127.0.0.1:9200/shopping/_doc

请求体中添加如下数据:

javascript 复制代码
{
    "title": "小米手机",
    "category": "小米",
    "images": "http://www.gulixueyuan.com/xm.jpg",
    "price": 3999.0
}

注意不能使用PUT请求,必须使用POST请求。数据插入成功后,会随机生成一个id,多次请求返回的id是不一样的,因此POST请求不是幂等性的。如果想指定id,可以写成如下形式:

POST http://127.0.0.1:9200/shopping/_doc/1001

此时返回的id就是1001:

如果指定id,就可以将请求方式改为PUT:

PUT http://127.0.0.1:9200/shopping/_doc/1002

还可以使用PUT请求指明是创建文档:

PUT http://127.0.0.1:9200/shopping/_create/1003

6)查询文档

根据指定id查询文档:

GET http://127.0.0.1:9200/shopping/_doc/1001

文档数据保存在_source字段中。

查询不存在的文档,返回结果中found为false:

全量查询指定索引下的文档:

GET http://127.0.0.1:9200/shopping/_search

  1. 更新文档

更新操作也可以用PUT,和创建是类似的

PUT http://127.0.0.1:9200/shopping/_doc/1001

这种更新成为全量数据的更新(本质上是覆盖式创建?),如果只需要更新部分字段,则使用POST方法:

POST http://127.0.0.1:9200/shopping/_update/1001

但此时body的内容需要修改,用doc字段包住需要修改的内容

8)删除文档

DELETE http://127.0.0.1:9200/shopping/_doc/1001

9)条件查询

查询category字段为小米的数据:

GET http://127.0.0.1:9200/shopping/_search**?q=category:小米**

将请求参数放在请求地址中比较麻烦,而且如果有中文可能出现乱码,因此一般是将参数放在请求体中:

GET http://127.0.0.1:9200/shopping/_search

请求体:

javascript 复制代码
{
    "query": {
        "match": {
            "category": "小米"    
        }
    }
}

10)分页查询

查询所有数据,并且进行分页:

GET http://127.0.0.1:9200/shopping/_search

javascript 复制代码
{
    "query": {
        "match_all": {

        }
    },
    "from": 0,
    "size": 2
}

指定字段查询:

GET http://127.0.0.1:9200/shopping/_search

javascript 复制代码
{
    "query": {
        "match_all": {

        }
    },
    "from": 0,
    "size": 2,
    "_source": ["title"]
}

查询后排序:

GET http://127.0.0.1:9200/shopping/_search

javascript 复制代码
{
    "query": {
        "match_all": {

        }
    },
    "from": 0,
    "size": 2,
    "_source": ["title"],
    "sort": {
        "price": {
            "order": "desc"
        }
    }
}

11)多条件查询和范围查询

014-入门-HTTP-多条件查询 & 范围查询

4. 全文检索和映射关系

如果条件查询的条件是category为"米",也会把category为"小米"的数据查询出来:

GET http://127.0.0.1:9200/shopping/_search

javascript 复制代码
{
    "query": {
        "match": {
            "category": "米"    
        }
    }
}

这是因为保存文档时,ES会进行分词操作,将分词后的结果保存在倒排索引中, 即使使用文字的一部分也能检索出数据,这就是全文检索。注意,ES在检索时也会对查询条件进行分词拆解,即输入"小华"也能查询出数据,因为"小华"会被拆解为"小"和"华"。如果想完全匹配,则需要修改请求体:

javascript 复制代码
{
    "query": {
        "match_phase": {
            "category": "小华"    
        }
    }
}

有的字段可以进行分词查询,有的字段则不行,这种字段可不可以进行分词查询保存在映射关系中。在创建索引时创建映射关系:

PUT http://127.0.0.1:9200/user/_mapping

javascript 复制代码
{
    "properties": [
        "name": {
            "type": "text", // 可以进行分词查询
            "index": true
        },
        "sex": {
            "type": "keyword", // 不可以进行分词查询,只能进行关键字查询
            "index": true
        },
        "tel": {
            "type": "keyword", // 不能进行索引
            "index": false
        }
    ]
}

查询索引关系:

GET http://127.0.0.1:9200/user/_mapping

根据name进行分词查询可以查出数据:

根据性别进行分词查询查不出数据(因为字段类型是keyword):

根据性别进行关键字查询可以查出数据:

根据电话进行查询查不出数据(因为字段是否索引为false)

高亮查询:015-入门-HTTP-全文检索 & 完全匹配 & 高亮查询_哔哩哔哩_bilibili

聚合查询:016-入门-HTTP-聚合查询_哔哩哔哩_bilibili

5. Java操作ElasticSearch

引入pom依赖:

XML 复制代码
<dependency>
    <groupId>org.elasticsearch</groupId>
    <artifactId>elasticsearch</artifactId>
    <version>7.8.0</version>
</dependency>
<dependency>
    <groupId>org.elasticsearch.client</groupId>
    <artifactId>elasticsearch-rest-high-level-client</artifactId>
    <version>7.4.2</version>
</dependency>

创建客户端连接ElasticSearch,然后关闭:

java 复制代码
// 创建ES客户端
RestHighLevelClient esClient = new RestHighLevelClient(
        RestClient.builder(new HttpHost("localhost", 9200, "http"))
);

// 关闭客户端
esClient.close();

创建索引:

java 复制代码
// 创建索引
CreateIndexRequest createIndexRequest = new CreateIndexRequest("user");
CreateIndexResponse createIndexResponse = esClient.indices().create(createIndexRequest, RequestOptions.DEFAULT);

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

查询索引:

java 复制代码
// 查询索引
GetIndexRequest getIndexRequest = new GetIndexRequest("user");
GetIndexResponse getIndexResponse = esClient.indices().get(getIndexRequest, RequestOptions.DEFAULT);

// 打印响应内容
System.out.println(getIndexResponse.getAliases());
System.out.println(getIndexResponse.getMappings());
System.out.println(getIndexResponse.getSettings());

删除索引:

java 复制代码
// 删除索引
DeleteIndexRequest deleteIndexRequest = new DeleteIndexRequest("user");
AcknowledgedResponse deleteResponse = esClient.indices().delete(deleteIndexRequest, RequestOptions.DEFAULT);

// 打印响应状态
System.out.println(deleteResponse.isAcknowledged());

向索引里面插入数据:

java 复制代码
// 插入数据
IndexRequest indexRequest = new IndexRequest();
indexRequest.index("user").id("1001");

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

ObjectMapper objectMapper = new ObjectMapper();
String userJson = objectMapper.writeValueAsString(user);

indexRequest.source(userJson, XContentType.JSON);
IndexResponse indexResponse = esClient.index(indexRequest, RequestOptions.DEFAULT);
System.out.println(indexResponse.getResult());

修改索引里的数据:

java 复制代码
// 更新数据
UpdateRequest updateRequest = new UpdateRequest();
updateRequest.index("user").id("1001");

updateRequest.doc(XContentType.JSON, "sex", "女");
UpdateResponse updateResponse = esClient.update(updateRequest, RequestOptions.DEFAULT);
System.out.println(updateResponse.getResult());

查询索引里的全量数据:

java 复制代码
// 查询数据
GetRequest getRequest = new GetRequest();
getRequest.index("user").id("1001");

GetResponse documentFields = esClient.get(getRequest, RequestOptions.DEFAULT);
System.out.println(documentFields.getSourceAsString());

删除数据:

java 复制代码
// 删除数据
DeleteRequest deleteRequest = new DeleteRequest();
deleteRequest.index("user").id("1001");

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

批量创建数据:

java 复制代码
// 批量增加数据
BulkRequest bulkRequest = new BulkRequest();
bulkRequest.add(new IndexRequest().index("user").id("1001").source(XContentType.JSON, "name", "zhangsan"));
bulkRequest.add(new IndexRequest().index("user").id("1002").source(XContentType.JSON, "name", "lisi"));
bulkRequest.add(new IndexRequest().index("user").id("1003").source(XContentType.JSON, "name", "wangwu"));

BulkResponse bulkResponse = esClient.bulk(bulkRequest, RequestOptions.DEFAULT);
System.out.println(bulkResponse.getTook()); // 查看耗时

批量删除数据:

java 复制代码
// 批量删除数据
BulkRequest bulkRequest = new BulkRequest();
bulkRequest.add(new DeleteRequest().index("user").id("1001"));
bulkRequest.add(new DeleteRequest().index("user").id("1002"));
bulkRequest.add(new DeleteRequest().index("user").id("1003"));

esClient.bulk(bulkRequest, RequestOptions.DEFAULT);

条件查询:

java 复制代码
// 条件查询
SearchRequest searchRequest = new SearchRequest();
searchRequest.indices("user");
// 全量查询
searchRequest.source(new SearchSourceBuilder().query(QueryBuilders.matchAllQuery()));

SearchResponse searchResponse = esClient.search(searchRequest, RequestOptions.DEFAULT);
SearchHits hits = searchResponse.getHits();
System.out.println(hits.getTotalHits());
System.out.println(searchResponse.getTook());
for (SearchHit hit : hits) {
    System.out.println(hit.getSourceAsString());
}

条件查询:

java 复制代码
SearchRequest searchRequest = new SearchRequest();
searchRequest.indices("user");
// 2. 条件查询
searchRequest.source(new SearchSourceBuilder().query(QueryBuilders.termQuery("age", 30)));

SearchResponse searchResponse = esClient.search(searchRequest, RequestOptions.DEFAULT);
SearchHits hits = searchResponse.getHits();
System.out.println(hits.getTotalHits());
System.out.println(searchResponse.getTook());
for (SearchHit hit : hits) {
    System.out.println(hit.getSourceAsString());
}

分页查询:

java 复制代码
// 3. 分页查询
SearchSourceBuilder builder = new SearchSourceBuilder().query(QueryBuilders.matchAllQuery());
builder.from(0).size(2);
searchRequest.source(builder);

SearchResponse searchResponse = esClient.search(searchRequest, RequestOptions.DEFAULT);
SearchHits hits = searchResponse.getHits();
System.out.println(hits.getTotalHits());
System.out.println(searchResponse.getTook());
for (SearchHit hit : hits) {
    System.out.println(hit.getSourceAsString());
}

查询排序:

java 复制代码
SearchSourceBuilder builder = new SearchSourceBuilder().query(QueryBuilders.matchAllQuery());
builder.sort("age", SortOrder.DESC);
searchRequest.source(builder);

SearchResponse searchResponse = esClient.search(searchRequest, RequestOptions.DEFAULT);
SearchHits hits = searchResponse.getHits();
System.out.println(hits.getTotalHits());
System.out.println(searchResponse.getTook());
for (SearchHit hit : hits) {
    System.out.println(hit.getSourceAsString());
}

查询指定字段:

java 复制代码
// 查询指定字段
SearchSourceBuilder builder = new SearchSourceBuilder().query(QueryBuilders.matchAllQuery());
String[] includes = {"name"};
String[] excludes = {};
builder.fetchSource(includes, excludes);
searchRequest.source(builder);

SearchResponse searchResponse = esClient.search(searchRequest, RequestOptions.DEFAULT);
SearchHits hits = searchResponse.getHits();
System.out.println(hits.getTotalHits());
System.out.println(searchResponse.getTook());
for (SearchHit hit : hits) {
    System.out.println(hit.getSourceAsString());
}

多条件查询:

java 复制代码
// 多条件查询
SearchSourceBuilder builder = new SearchSourceBuilder();
builder.query(QueryBuilders.boolQuery()
        .must(QueryBuilders.matchQuery("age", 30))
        .must(QueryBuilders.matchQuery("sex", "男")));
searchRequest.source(builder);

SearchResponse searchResponse = esClient.search(searchRequest, RequestOptions.DEFAULT);
SearchHits hits = searchResponse.getHits();
System.out.println(hits.getTotalHits());
System.out.println(searchResponse.getTook());
for (SearchHit hit : hits) {
    System.out.println(hit.getSourceAsString());
}

将性别改成女(使用mustNot方法):

java 复制代码
// 多条件查询
SearchSourceBuilder builder = new SearchSourceBuilder();
builder.query(QueryBuilders.boolQuery()
        .must(QueryBuilders.matchQuery("age", 30))
        .mustNot(QueryBuilders.matchQuery("sex", "男")));
searchRequest.source(builder);

SearchResponse searchResponse = esClient.search(searchRequest, RequestOptions.DEFAULT);
SearchHits hits = searchResponse.getHits();
System.out.println(hits.getTotalHits());
System.out.println(searchResponse.getTook());
for (SearchHit hit : hits) {
    System.out.println(hit.getSourceAsString());
}

must表示与,should表示或:

java 复制代码
SearchSourceBuilder builder = new SearchSourceBuilder();
builder.query(QueryBuilders.boolQuery()
        .should(QueryBuilders.matchQuery("age", 30))
        .should(QueryBuilders.matchQuery("age", 40)));
searchRequest.source(builder);

SearchResponse searchResponse = esClient.search(searchRequest, RequestOptions.DEFAULT);
SearchHits hits = searchResponse.getHits();
System.out.println(hits.getTotalHits());
System.out.println(searchResponse.getTook());
for (SearchHit hit : hits) {
    System.out.println(hit.getSourceAsString());
}

模糊查询:

java 复制代码
// 模糊查询
SearchSourceBuilder builder = new SearchSourceBuilder();
// 模糊查询,差1个就可以查出
builder.query(QueryBuilders.fuzzyQuery("name", "wangwu").fuzziness(Fuzziness.ONE));
searchRequest.source(builder);

SearchResponse searchResponse = esClient.search(searchRequest, RequestOptions.DEFAULT);
SearchHits hits = searchResponse.getHits();
System.out.println(hits.getTotalHits());
System.out.println(searchResponse.getTook());
for (SearchHit hit : hits) {
    System.out.println(hit.getSourceAsString());
}

聚合查询,查询最大年龄:

java 复制代码
// 聚合查询
SearchSourceBuilder builder = new SearchSourceBuilder();
AggregationBuilder aggregationBuilder = AggregationBuilders.max("maxAge").field("age");
builder.aggregation(aggregationBuilder);
searchRequest.source(builder);

SearchResponse searchResponse = esClient.search(searchRequest, RequestOptions.DEFAULT);
SearchHits hits = searchResponse.getHits();
System.out.println(hits.getTotalHits());
System.out.println(searchResponse.getTook());
for (SearchHit hit : hits) {
    System.out.println(hit.getSourceAsString());
}

分组查询:

java 复制代码
// 分组查询
SearchSourceBuilder builder = new SearchSourceBuilder();
AggregationBuilder aggregationBuilder = AggregationBuilders.terms("ageGroup").field("age");
builder.aggregation(aggregationBuilder);
searchRequest.source(builder);

SearchResponse searchResponse = esClient.search(searchRequest, RequestOptions.DEFAULT);
SearchHits hits = searchResponse.getHits();
System.out.println(hits.getTotalHits());
System.out.println(searchResponse.getTook());
for (SearchHit hit : hits) {
    System.out.println(hit.getSourceAsString());
}
相关推荐
Dreams°12343 分钟前
大数据 ETL + Flume 数据清洗 — 详细教程及实例(附常见问题及解决方案)
大数据·单元测试·可用性测试
sf_www1 小时前
Flink on YARN是如何确定TaskManager个数的
大数据·flink
infiniteWei1 小时前
【Lucene】原理学习路线
学习·搜索引擎·全文检索·lucene
武子康2 小时前
大数据-213 数据挖掘 机器学习理论 - KMeans Python 实现 距离计算函数 质心函数 聚类函数
大数据·人工智能·python·机器学习·数据挖掘·scikit-learn·kmeans
武子康2 小时前
大数据-214 数据挖掘 机器学习理论 - KMeans Python 实现 算法验证 sklearn n_clusters labels
大数据·人工智能·python·深度学习·算法·机器学习·数据挖掘
Aloudata3 小时前
NoETL自动化指标平台为数据分析提质增效,驱动业务决策
大数据·数据分析·指标平台·指标体系
2401_883041087 小时前
新锐品牌电商代运营公司都有哪些?
大数据·人工智能
青云交7 小时前
大数据新视界 -- 大数据大厂之 Impala 性能优化:融合机器学习的未来之路(上 (2-1))(11/30)
大数据·计算资源·应用案例·数据交互·impala 性能优化·机器学习融合·行业拓展
Json_1817901448010 小时前
An In-depth Look into the 1688 Product Details Data API Interface
大数据·json
Qspace丨轻空间12 小时前
气膜场馆:推动体育文化旅游创新发展的关键力量—轻空间
大数据·人工智能·安全·生活·娱乐