目录

写在前面

一、下载地址

二、solr与es比较

三、安装elasticsearch

四、安装可视化界面(hand插件)

使用

五、安装kibana

六、学习es核心概念

七、IK分词器插件

八、使用ES

九、es的复杂查询

十、集成Springboot

十一、京东搜索


写在前面

ES(ElasticSearch)相信很多小伙伴都听过它的鼎鼎大名,但是一直不知道其是如何工作的,今天就靠这一篇文章将它彻底入门!

一、下载地址

因为ES及其部分插件,国内下载速度比较慢,这里贴出来华为云的下载链接,速度刚刚的!

ElasticSearch: https://mirrors.huaweicloud.com/elasticsearch/?C=N&O=D

logstash: https://mirrors.huaweicloud.com/logstash/?C=N&O=D

kibana: https://mirrors.huaweicloud.com/kibana/?C=N&O=D

elasticsearch-analysis-ik: https://github.com/medcl/elasticsearch-analysis-ik/releases

cerebro: https://github.com/lmenezes/cerebro/releases

head:https://github.com/mobz/elasticsearch-head

二、solr与es比较

1.es基本开箱即用(解压就可以用!),非常简单。Solr安装稍微复杂一丢丢!

2.Solr利用Zookeeper进行分布式管理,而Es自身带有分布式协调管理功能。

3.Solr支持更多格式的数据,比如JSON、XML、CSV,而Es仅支持json文件格式。

4.Solr官方提供的功能更多,而Elasticsearch本身更注重核心功能,高级功能多有第三方插件提供,例如图形化界面需要kibana友好支撑。

5.Solr查询块,但更新索引时慢(即插入删除慢),用于电商等查询多的应用;

ES建立索引快(即查询慢),即实时性查询块,用于facebook新浪等搜索;

Solr是传统搜索应用的有力解决方案,但Elasticsearch更适用于新兴的实时搜索应用。

6.Solr比较成熟,有一个更大,更成熟的用户、开发和贡献者社区,而Elasticsearch相对开发维护者较少,更新太快,学习使用成本较高。

三、安装elasticsearch

要求:jdk1.8以上。

1.解压即可使用。

jvm.options是jvm的配置文件,默认内存1G。

elasticsearch.yml是es的配置文件,默认9200端口,通信端口是9300。

modules是功能模块。

plugins是第三方插件。

2.启动。

双击bin/elasticsearch.bat

3.输入网址

http://localhost:9200/

{"name" : "DESKTOP-BA2JN2H","cluster_name" : "elasticsearch","cluster_uuid" : "BJx-AEKcQoacSXfZhpCI5A","version" : {"number" : "7.6.0","build_flavor" : "default","build_type" : "zip","build_hash" : "7f634e9f44834fbc12724506cc1da681b0c3b1e3","build_date" : "2020-02-06T00:09:00.449973Z","build_snapshot" : false,"lucene_version" : "8.4.0","minimum_wire_compatibility_version" : "6.8.0","minimum_index_compatibility_version" : "6.0.0-beta1"},"tagline" : "You Know, for Search"
}

四、安装可视化界面(hand插件)

1.必须安装node.js。

2.npm安装

* git clone git://github.com/mobz/elasticsearch-head.git
* cd elasticsearch-head
* npm install
* npm run start
* open http://localhost:9100/

3.解决es跨域问题

elasticsearch.yml配置文件

http.cors.enabled: true
http.cors.allow-origin: "*"

4.打开http://localhost:9100/

连接http://localhost:9200/

使用

5.初学,就把es当做一个数据库。索引就相当于一个数据库,文档就相当于数据。

这个hand把它当成一个数据展示工具,后面所有的查询可以在kibana做。

五、安装kibana

kibana版本要和es版本一致!

1.解压。

2.启动(也需要安装node.js)

bin/kibana.bat

3.访问http://localhost:5601

4.汉化

\kibana-7.6.0-windows-x86_64\x-pack\plugins\translations\translations\下面有汉化文件。

config/kibana.yml下配置:

i18n.locale: "zh-CN"

5.开发工具

六、学习es核心概念

1.elasticsearch是面向文档的数据库。关系型数据库和elasticsearch客观的对比:

Relational DB(MySQL)

Elasticsearch

数据库(database)

索引(indices)(就和数据库一样)

表(tables)

类型types(慢慢会被弃用)

行(rows)

文档documents

字段(columns)

字段fields

elasticsearch(集群)中可以包含多个索引(数据库),每个索引中可以包含多个类型(表),每个类型下又包含多个文档(行),每个文档中又包含多个字段(列)。

2.物理设计

elasticsearch在后台把每个索引划分成多个分片,每分分片可以在集群中的不同服务器间迁移。

一个人就是一个集群!默认的集群名称就是elasticsearch。

3.逻辑设计

一个索引类型中,包含多个文档,比如说文档1,文档2。当我们索引一篇文档时,可以通过这样的一个顺序找到它:索引 ->类型 -> 文档ID,通过这个组合我们就能索引到某个具体的文档。注意:ID不必是整数,实际上它是个字符串。

①文档(就是一条条数据):

之前说 elasticsearch是面向文档的,那么就意味着索引和搜索数据的最小单位是文档,elasticsearch中,文档有几个重要属性:

(1)自我包含,一篇文档同时包含字段和对应的值,也就是同时包含 key: value!

(2)可以是层次型的,一个文档中包含自文档,复杂的逻辑实体就是这么来的!{就是一个json对象!}

(3)灵活的结构,文档不依赖预先定义的模式,我们知道关系型数据库中,要提前定义字段才能使用,在elasticsearch中,对于字段是非常灵活的,有时候,我们可以忽略该字段,或者动态的添加一个新的字段。

尽管我们可以随意的新増或者忽略某个字段,但是,每个字段的类型非常重要,比如一个年龄字段类型,可以是字符串也可以是整形。因为 elasticsearch会保存字段和类型之间的映射及其他的设置。这种映射具体到毎个映射的每种类型,这也是为什么在elasticsearch中,类型有时候也称为映射类型。

②类型(较少去用了)

类型是文档的逻辑容器,就像关系型数据库一样,表格是行的容器。类型中对于字段的定义称为映射,比如name映射为字符串类型。我们说文档是无模式的,它们不需要拥有映射中所定义的所有字段,比如新增一个字段,那么 elasticsearch是怎么做的呢?elasticsearch会自动的将新字段加入映射,但是这个字段的不确定它是什么类型, elasticsearch就开始猜,如果这个值是18,那么elasticsearch会认为它是整形。但是 elastirsearch也可能猜不对,所以最安全的方式就是提前定义好所需要的映射,这点跟关系型数据库殊途同归了,先定义好字段,然后再使用,别整什么幺蛾子。

③索引

索引就是数据库!

索引是映射类型的容器, elasticsearch中的索引是一个非常大的文档集合。索引存储了映射类型的字段和其他设置。然后它们被存储到了各个分片上了。我们来研究下分片是如何工作的。

4.物理设计:节点和分片如何工作

一个集群至少有一个节点,,而一个节点就是一个 elasticsearch进程,节点可以有多个索引默认的,如果你创建索引,那么索引将会有个5个分片( primary shard,又称主分片)构成的,每一个主分片会有一个副本( replica shard,又称复制分片)

上图是一个有3个节点的集群,可以看到主分片和对应的复制分片都不会在同一个节点内,这样有利于某个节点挂掉了,数据也不至于丢失。实际上,一个分片是一个 Lucene索引,一个包含倒排索引图的文件目录,倒排索引的结构使得 elasticsearch在不扫描全部文档的情况下,就能告诉你哪些文档包含特定的关键字。不过,等等,倒排索引是什么鬼?

5.倒排索引

elasticsearch使用的是一种称为倒排索引的结构,采用 Lucene倒排索作为底层。这种结构适用于快速的全文搜索,一个索引由文档中所有不重复的列表构成,对于每一个词,都有一个包含它的文档列表。例如,现在有两个文档,每个文档包含如下内容:

为了创建倒排索引,我们首先要将每个文档拆分成独立的词(或称为词条或者 tokens),然后创建一个包含所有不重复的词条的排序列表,然后列出每个词条出现在哪个文档。

现在我们试图搜索to forever,只需要查看包含每个词条的文档。

两个文档都匹配,但是第一个文档比第二个匹配程度更高。如果没有别的条件,现在,这两个包含关键字的文档都将返回。

再来看一个示例,比如我们通过博客标签来搜索博客文章。那么倒排索引列表就是这样的一个结构:

如果要搜索含有 python标签的文章,那相对于査找所有原始数据而言,査找倒排索引后的数据将会快的多。只需要査看标签这栏,然后获取相关的文章ID即可。完全过滤掉无关的所有数据,提高效率!

elasticsearch的索引和 Lucene的索引对比:

在 elasticsearch中,索引这个词被频繁使用,这就是术语的使用。在 elasticsearch中,索引被分为多个分片,每份分片是一个Lucene的索引。所以一个 elasticsearch索引是由多个 Lucene索引组成的。别问为什么,谁让 elasticsearchy使用 Lucene作为底层呢!如无特指,说起索引都是指 elasticsearch的索引。

七、IK分词器插件

1.什么是IK分词器

分词:即把一段中文或者别的划分成一个个的关键字,我们在搜索时候会把自己的信息进行分词,会把数据库中或者索引库中的数据进行分词,然后进行—个匹配操作,默认的中文分词是将毎个字看成一个词,比如“我爱狂神”会被分为"我""爱""狂"神",这显然是不符合要求的,所以我们需要安装中文分词器IK来解决这个问题。

如果要使用中文,建议使用IK分词器!

IK提供了两个分词算法: ik_smart和 ik_max_word,其中 ik_smart为最少切分,ik_max_word为最细粒度划分!

2.下载安装(下载与es对应的版本!!!否则会启动报错)

①下载完,解压到ES目录下

D:\es\elasticsearch-7.6.0\plugins\elasticsearch-analysis-ik-7.6.0

②重启es,会出现加载ik插件

[2021-05-07T09:51:29,253][INFO ][o.e.p.PluginsService     ] [DESKTOP-KAO1R1F] loaded plugin [analysis-ik]

③使用elasticsearch-plugin.bat,查看插件

3.使用kibana测试

GET _analyze
{"analyzer" : "ik_smart","text" : "中国共产党"
}{"tokens" : [{"token" : "中国共产党","start_offset" : 0,"end_offset" : 5,"type" : "CN_WORD","position" : 0}]
}
GET _analyze
{"analyzer" : "ik_max_word","text" : "中国共产党"
}{"tokens" : [{"token" : "中国共产党","start_offset" : 0,"end_offset" : 5,"type" : "CN_WORD","position" : 0},{"token" : "中国","start_offset" : 0,"end_offset" : 2,"type" : "CN_WORD","position" : 1},{"token" : "国共","start_offset" : 1,"end_offset" : 3,"type" : "CN_WORD","position" : 2},{"token" : "共产党","start_offset" : 2,"end_offset" : 5,"type" : "CN_WORD","position" : 3},{"token" : "共产","start_offset" : 2,"end_offset" : 4,"type" : "CN_WORD","position" : 4},{"token" : "党","start_offset" : 4,"end_offset" : 5,"type" : "CN_CHAR","position" : 5}]
}

②有些词被拆分了,需要自己来配置分词

重启es看细节

[2021-05-07T10:21:48,875][INFO ][o.e.g.GatewayService     ] [DESKTOP-KAO1R1F] recovered [5] indices into cluster_state
[2021-05-07T10:21:49,223][INFO ][o.w.a.d.Monitor          ] [DESKTOP-KAO1R1F] try load config from D:\es\elasticsearch-7.6.0\config\analysis-ik\IKAnalyzer.cfg.xml
[2021-05-07T10:21:49,228][INFO ][o.w.a.d.Monitor          ] [DESKTOP-KAO1R1F] try load config from D:\es\elasticsearch-7.6.0\plugins\elasticsearch-analysis-ik-7.6.0\config\IKAnalyzer.cfg.xml
[2021-05-07T10:21:49,751][INFO ][o.w.a.d.Monitor          ] [DESKTOP-KAO1R1F] [Dict Loading] D:\es\elasticsearch-7.6.0\plugins\elasticsearch-analysis-ik-7.6.0\config\cxf.dic

八、使用ES

1.基本REST

2.基础索引测试

①创建索引

格式:
PUT /索引名/(类型名,以后可能不会用到了)/文档id
{请求体}示例:
PUT /test1/type1/1
{"name" : "永远的神","age" : 3
}#! Deprecation: [types removal] Specifying types in document index requests is deprecated, use the typeless endpoints instead (/{index}/_doc/{id}, /{index}/_doc, or /{index}/_create/{id}).
{"_index" : "test1","_type" : "type1","_id" : "1","_version" : 1,"result" : "created","_shards" : {"total" : 2,"successful" : 1,"failed" : 0},"_seq_no" : 0,"_primary_term" : 1
}

完成了自动增加了索引!数据也添加成功了!索引初期可以当做一个数据库!

②指定字段的类型

text类型会被分词解析,keyword是不会被分词解析的!

创建规则:
PUT /test2
{"mappings": {"properties": {"name" : {"type" :"text"},"age" : {"type" : "long"},"birthday" : {"type" : "date"}}}
}

③获得数据信息

GET /test2

④查看默认的信息

如果没有指定字段类型,那么es会自动设置默认的字段类型

PUT /test3/_doc/1
{"name" : "张三","age" : 18
}使用GET:
GET /test3
结果:
{"test3" : {"aliases" : { },"mappings" : {"properties" : {"age" : {"type" : "long"},"name" : {"type" : "text","fields" : {"keyword" : {"type" : "keyword","ignore_above" : 256}}}}},"settings" : {"index" : {"creation_date" : "1620355778195","number_of_shards" : "1","number_of_replicas" : "1","uuid" : "b4ATwfKGQ9yoNgB2ce-UOA","version" : {"created" : "7060099"},"provided_name" : "test3"}}}
}
获取健康状态
GET _cat/health1620356456 03:00:56 elasticsearch yellow 1 1 12 12 0 0 8 0 - 60.0%查看信息
GET _cat/indices?vhealth status index                      uuid                   pri rep docs.count docs.deleted store.size pri.store.size
yellow open   test2                      n1Yl5LvZSlyGrsirb3JyrQ   1   1          0            0       283b           283b
yellow open   test3                      b4ATwfKGQ9yoNgB2ce-UOA   1   1          1            0      3.7kb          3.7kb
green  open   .kibana_task_manager_1     uwnOx-ktSl-kLenHmgyQhg   1   0          2            0       13kb           13kb
green  open   .apm-agent-configuration   ESfhRweTTxOjx_5NFH0V7Q   1   0          0            0       283b           283b
green  open   kibana_sample_data_flights RXgt4tWjQNqbAMEZnleV3g   1   0      13059            0      6.2mb          6.2mb
green  open   .kibana_1                  w_wKw0LxQEitRAWALeQSng   1   0         80            3    136.9kb        136.9kb
yellow open   test1                      SCHGcDpZRYGvTGhhXjqaEg   1   1          1            0      3.7kb          3.7kb
yellow open   db                         r1AqWtE1Q_i2I4kwcpMvZQ   5   1          0            0      1.3kb          1.3kb

⑤修改

1.直接覆盖:
PUT /test3/_doc/1
{"name" : "李四","age" : 18
}修改之后版本号会+12.使用POST修改
POST /test3/_doc/1/_update
{"doc" : {"name" : "王五"}
}

⑥删除

DELETE /test3/_doc/1DELETE /test3

3.关于文档的操作

①添加数据:

PUT /cxf/user/1
{"name" : "张三","age" : 24,"desc" : "永远的神","tags" : ["强", "温暖", "博爱"]
}PUT /cxf/user/2
{"name" : "张四","age" : 25,"desc" : "永远的2","tags" : ["旅游", "玩游戏", "渣男"]
}PUT /cxf/user/3
{"name" : "张五","age" : 22,"desc" : "永远的5","tags" : ["玩", "逛街", "帅b"]
}

②获取数据:

GET /cxf/user/3

③更新数据:

PUT是完全覆盖,POST修改是修改指定的属性

PUT /cxf/user/3
{"name" : "张四2","age" : 25,"desc" : "永远的2","tags" : ["旅游", "玩游戏", "渣男"]
}POST /cxf/user/3/_update
{"doc" : {"name" : "张四4"}
}

九、es的复杂查询

查询出来的东西:

hits:索引和文档的信息。

total:查询结果总数。

然后就是查询出来的具体文档。

数据中的东西都可以遍历出来了。

分数:我们可以通过来判断谁更加符合结果。

#! Deprecation: [types removal] Specifying types in search requests is deprecated.
{"took" : 2,"timed_out" : false,"_shards" : {"total" : 1,"successful" : 1,"skipped" : 0,"failed" : 0},"hits" : {"total" : {"value" : 3,"relation" : "eq"},"max_score" : 0.6409958,"hits" : [{"_index" : "cxf","_type" : "user","_id" : "2","_score" : 0.6409958,"_source" : {"name" : "张四","age" : 25,"desc" : "永远的2","tags" : ["旅游","玩游戏","渣男"]}},{"_index" : "cxf","_type" : "user","_id" : "3","_score" : 0.5403744,"_source" : {"name" : "张四4","age" : 25,"desc" : "永远的2","tags" : ["旅游","玩游戏","渣男"]}},{"_index" : "cxf","_type" : "user","_id" : "1","_score" : 0.14181954,"_source" : {"name" : "张三","age" : 24,"desc" : "永远的神","tags" : ["强","温暖","博爱"]}}]}
}
1.通过id查询:
GET /cxf/user/3
2.条件查询:
GET /cxf/user/_search?q=name:张三3.query查询:
GET /cxf/user/_search
{"query": {"match": {"name": "张四" // 匹配属性值}},"_source" : ["name", "age"] // 结果过滤, "sort": [ // 排序,排序之后分值就为null了{"age": {"order": "desc"}}],"from": 0, // 分页,相当于limit。from是从第几条开始,size是每页多少条数据"size": 2
}4.多条件精确查询:
GET /cxf/user/_search
{"query": {"bool": {"must": [ // 相当于mysql的and,所有的条件都要符合{"match": {"name": "张三"}},{"match": {"age": 24}}]}}
}5.or操作:
GET /cxf/user/_search
{"query": {"bool": {"should": [ // 等价于or{"match": {"name": "张三"}},{"match": {"age": 25}}]}}
}6.查询不是
GET /cxf/user/_search
{"query": {"bool": {"must_not": [ // 等价于!={"match": {"name": "三"}},{"match": {"age": 24}}]}}
}7.过滤条件
GET /cxf/user/_search
{"query": {"bool": {"must": [{"match": {"name": "张三"}}],"filter": {"range": {"age": {"gte": 10, // 查询条件"lte": 24}}}}}
}
gt:大于
gte:大于等于
lt:小于
lte:小于等于8.匹配多个条件
多条件用空格隔开,只要满足其中一个结果既可以被查出,这个时候可以通过分值进行判断。
GET /cxf/user/_search
{"query": {"match": {"tags": "男 游戏"}}
}9.精确查询
term查询是直接通过倒排查询进行精确查询的。
term是直接查询精确的值。
match会使用分词器。(先分析文档,然后再通过分析的文档进行查询!)
text类型会被分词解析,keyword是不会被分词解析的!
GET /cxf/user/_search
{"query": {"term": {"name": {"value": "张四"}}}
}10.高亮查询
GET /cxf/user/_search
{"query": {"match": {"name": "张三"}},"highlight": { // 搜索的高亮条件,会自动增加<em>张</em>标签"pre_tags": "<p class='key' style='color:red'>", // 自定义高亮标签"post_tags": "</p>","fields": {"name":{}}}
}

十、集成Springboot

1.pom

<dependency><groupId>org.elasticsearch.client</groupId><artifactId>elasticsearch-rest-high-level-client</artifactId><version>7.6.0</version>
</dependency>properties中需要指定es版本:
<elasticsearch.version>7.6.0</elasticsearch.version><!--elasticsearch-->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>

2.配置

import org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class ElasticsearchConfig {@Beanpublic RestHighLevelClient restHighLevelClient(){RestHighLevelClient restHighLevelClient = new RestHighLevelClient(RestClient.builder(new HttpHost("127.0.0.1", 9200, "http")));return restHighLevelClient;}
}

3.具体api

import com.alibaba.fastjson.JSON;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.client.indices.CreateIndexResponse;
import org.elasticsearch.client.indices.GetIndexRequest;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.MatchQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.FetchSourceContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import java.io.IOException;
import java.util.ArrayList;
import java.util.concurrent.TimeUnit;@RequestMapping("/es")
@Controller
public class ElasticsearchController {@Autowired@Qualifier("restHighLevelClient")private RestHighLevelClient client;/*** 索引*/@RequestMapping("/test1")public void test1() throws IOException {// 创建索引CreateIndexRequest indexCui = new CreateIndexRequest("cui");CreateIndexResponse resp = client.indices().create(indexCui, RequestOptions.DEFAULT);System.out.println(resp);// 判断索引是否存在GetIndexRequest getIndexRequest = new GetIndexRequest("cui");boolean exists = client.indices().exists(getIndexRequest, RequestOptions.DEFAULT);System.out.println(exists);//删除索引DeleteIndexRequest deleteIndexRequest = new DeleteIndexRequest("cui");AcknowledgedResponse delete = client.indices().delete(deleteIndexRequest, RequestOptions.DEFAULT);System.out.println(delete);}/*** POST添加数据*/@RequestMapping("/test2")public void test2() throws IOException {EsUser esUser = new EsUser();esUser.age =18;esUser.name = "张三";// 连接索引IndexRequest cui = new IndexRequest("cui");//规则 /cui/_doc/1cui.id("1");cui.timeout(TimeValue.timeValueSeconds(10));//cui.timeout("10s");// 请求体放进去cui.source(JSON.toJSONString(esUser), XContentType.JSON);//客户端发送请求IndexResponse index = client.index(cui, RequestOptions.DEFAULT);System.out.println(index);// 第一次是created,以后再添加就是update了}/*** 文档操作*/@RequestMapping("/test3")public void test3() throws IOException {/*** 判断文档是否存在*/GetRequest cui = new GetRequest("cui", "1");//不获取返回的上下文(_source)cui.fetchSourceContext(new FetchSourceContext(false));cui.storedFields("_none_");boolean exists = client.exists(cui, RequestOptions.DEFAULT);System.out.println(exists);GetRequest idx = new GetRequest("cui", "1");GetResponse documentFields = client.get(idx, RequestOptions.DEFAULT);System.out.println(documentFields.getSourceAsString());// 打印文档内容System.out.println(documentFields); // 返回的全部内容和命令是一样的/*** 更新*/EsUser esUser = new EsUser();esUser.age =19;esUser.name = "张四";UpdateRequest cui1 = new UpdateRequest("cui", "1");cui1.timeout("1s");cui1.doc(JSON.toJSONString(esUser), XContentType.JSON);UpdateResponse update = client.update(cui1, RequestOptions.DEFAULT);System.out.println(update);/*** 删除*/DeleteRequest cui2 = new DeleteRequest("cui", "1");cui2.timeout("1s");DeleteResponse delete = client.delete(cui2, RequestOptions.DEFAULT);System.out.println(delete);}/*** 批量操作*/@RequestMapping("/test4")public void test4() throws IOException {BulkRequest bulkRequest = new BulkRequest();bulkRequest.timeout("10s");ArrayList<EsUser> list = new ArrayList<>();list.add(new EsUser("崔1", 21));list.add(new EsUser("崔2", 22));list.add(new EsUser("崔3", 23));list.add(new EsUser("崔4", 24));list.add(new EsUser("崔5", 25));list.add(new EsUser("崔6", 26));list.add(new EsUser("崔7", 27));//批处理for (int i = 0; i < list.size(); i++) {// 批量修改删除,对应修改即可bulkRequest.add(new IndexRequest("cui").id(i + 1 + "") // 不写id会随机生成id.source(JSON.toJSONString(list.get(i)), XContentType.JSON));}BulkResponse bulk = client.bulk(bulkRequest, RequestOptions.DEFAULT);System.out.println(bulk);}/*** 查询* 就是对应基本的所有命令*/@RequestMapping("/test5")public void test5() throws IOException {SearchRequest searchRequest = new SearchRequest("cui");SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();//使用QueryBuilders,快速匹配查询条件MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("name", "崔1");searchSourceBuilder.query(matchQueryBuilder).from(0)// 分页.size(10).timeout(new TimeValue(10, TimeUnit.SECONDS));//searchSourceBuilder.highlighter();// 高亮searchRequest.source(searchSourceBuilder);// 把查询条件放到searchRequestSearchResponse search = client.search(searchRequest, RequestOptions.DEFAULT);System.out.println(search.getHits());// 文档内容System.out.println(search);for (SearchHit documentFields : search.getHits().getHits()) {System.out.println(documentFields.getSourceAsMap());// 遍历}}}class EsUser{public String name;public Integer age;public EsUser(String name, Integer age) {this.name = name;this.age = age;}public EsUser() {}
}

十一、京东搜索

1.导入包

<!--解析网页 jsoup  ;  tika包是解析视频音乐的-->
<dependency><groupId>org.jsoup</groupId><artifactId>jsoup</artifactId><version>1.10.2</version>
</dependency>

2.代码

import org.jsoup.Connection;
import org.jsoup.helper.HttpConnection;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;public class HtmlParseUtils {public static void main(String[] args) throws IOException {ArrayList<Info> java = HtmlParseUtils.getInfo("java");for (Info info : java) {System.out.println(info);}}public static ArrayList<Info> getInfo(String info) throws IOException {// 获取请求String url = "https://search.jd.com/Search?keyword=" + info;//解析网页(解析返回的document就是浏览器的document对象)URL u = new URL(url);Connection con = HttpConnection.connect(url);con.timeout(300000);con.header("User-Agent", "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36 Core/1.70.3861.400 QQBrowser/10.7.4313.400");con.header("cookie", "unpl=V2_ZzNtbURREEF3XxZReBAPVWIBRllKBUEQcw0VAyxOWVJhCkcIclRCFnUUR1BnGFUUZgoZWUNcQhFFCEdkeBBVAWMDE1VGZxBFLV0CFSNGF1wjU00zQwBBQHcJFF0uSgwDYgcaDhFTQEJ2XBVQL0oMDDdRFAhyZ0AVRQhHZH8ZXQBmBxteRmdzEkU4dl1yEV4DZTMTbUNnAUEpC0dSchtZSGMDE1hDU0oWcThHZHg%3d; __jdv=76161171|baidu-pinzhuan|t_288551095_baidupinzhuan|cpc|0f3d30c8dba7459bb52f2eb5eba8ac7d_0_77be3fa428ba43e59c3474bfff4f78dd|1620435006518; __jdu=510405825; areaId=13; ipLoc-djd=13-1007-37918-0; PCSYCityID=CN_370000_370200_370212; shshshfpa=b63cfa52-dd75-9d21-c820-0ae5f6a96ef1-1620435009; shshshfpb=abapWi%2F0i4o6AgQnM%2F5q%2F%2FQ%3D%3D; __jda=122270672.510405825.1620435006.1620435006.1620435007.1; __jdc=122270672; shshshfp=11c5062f56e8e6ad00ad498a9d3ab294; rkv=1.0; wlfstk_smdl=iycergr2qqxobmcam67n8ptxywbmufhd; qrsc=3; __jdb=122270672.8.510405825|1.1620435007; shshshsID=6e200de4a4e9605b03810b2ab647eb98_6_1620437334053; 3AB9D23F7A4B3C9B=RMWCKZRXMVHOY7FERSQDF7FV25CGZRNEEBLRZZLDHQWLBCLNY3I57D76RTH27WDER2KFJOAIHWKZJH7YDX7KREP5VA");Document document = con.get();//Document document = Jsoup.parse(u, 300000); // 京东这里会跳转到登录,咱们加上cookie// 所有js中能使用的方法,这里都能用Element j_goodsList = document.getElementById("J_goodsList");//获取所有li标签Elements li = j_goodsList.getElementsByTag("li");ArrayList<Info> list = new ArrayList<>();for (Element element : li) {String img = element.getElementsByTag("img").eq(0).attr("data-lazy-img");String price = element.getElementsByClass("p-price").eq(0).text();String name = element.getElementsByClass("p-name").eq(0).text();Info infos = new Info();infos.img = img;infos.name = name;infos.price = price;list.add(infos);}return list;}
}class Info{String img;String price;String name;public String getImg() {return img;}public void setImg(String img) {this.img = img;}public String getPrice() {return price;}public void setPrice(String price) {this.price = price;}public String getName() {return name;}public void setName(String name) {this.name = name;}@Overridepublic String toString() {return "Info{" +"img='" + img + '\'' +", price='" + price + '\'' +", name='" + name + '\'' +'}';}
}
import com.alibaba.fastjson.JSON;
import org.apache.http.HttpHost;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.MatchQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;public class EsTest {private static RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(new HttpHost("127.0.0.1", 9200, "http")));public static void main(String[] args) throws IOException {// insert();// 入库// 查询List<Map<String, Object>> java = searchPage("java", 0, 10);if(java.size() == 0){System.out.println("无数据");return;}for (Map<String, Object> stringObjectMap : java) {System.out.println(stringObjectMap);}}/*** 批量入库* @throws IOException*/public static void insert() throws IOException {// 批量添加ArrayList<Info> list = HtmlParseUtils.getInfo("大数据");BulkRequest bulkRequest = new BulkRequest();bulkRequest.timeout("10s");//批处理for (int i = 0; i < list.size(); i++) {// 批量修改删除,对应修改即可bulkRequest.add(new IndexRequest("jingdong")//.id(i + 1 + "") // 不写id会随机生成id.source(JSON.toJSONString(list.get(i)), XContentType.JSON));}BulkResponse bulk = client.bulk(bulkRequest, RequestOptions.DEFAULT);System.out.println(bulk);}public static List<Map<String, Object>> searchPage(String key, int pageNo, int pageSize) throws IOException {if(pageNo < 0){pageNo = 0;}SearchRequest searchRequest = new SearchRequest("jingdong");SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();//使用QueryBuilders,快速匹配查询条件MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("name", key);searchSourceBuilder.query(matchQueryBuilder).from(pageNo)// 分页.size(pageSize).timeout(new TimeValue(10, TimeUnit.SECONDS));//searchSourceBuilder.highlighter();// 高亮//高亮HighlightBuilder highlightBuilder = new HighlightBuilder();highlightBuilder.field("name").requireFieldMatch(false) //多个高亮显示.preTags("<span style='color:red'>").postTags("</span>");searchSourceBuilder.highlighter(highlightBuilder);searchRequest.source(searchSourceBuilder);// 把查询条件放到searchRequestSearchResponse search = client.search(searchRequest, RequestOptions.DEFAULT);//System.out.println(search.getHits());// 文档内容//System.out.println(search);List<Map<String, Object>> list = new ArrayList<>();for (SearchHit documentFields : search.getHits().getHits()) {//System.out.println(documentFields.getSourceAsMap());// 遍历Map<String, Object> sourceAsMap = documentFields.getSourceAsMap();// 原来的HighlightField name = documentFields.getHighlightFields().get("name"); // 获取name高亮if(name != null){//替换高亮字段Text[] fragments = name.fragments();String newName = "";for (Text fragment : fragments) {newName += fragment;}sourceAsMap.put("name", newName);// 替换原来的name// 高亮之后,使用v-html解析即可}list.add(sourceAsMap);}return list;}}

elasticSearch入门到java操作api一套搞定相关推荐

  1. ElasticSearch入门-搜索(java api)

    ElasticSearch入门-搜索(java api) package com.qlyd.searchhelper;import java.util.Map;import net.sf.json.J ...

  2. Elasticsearch入门(二) API

    Elasticsearch入门(二) API VSCode部署 RESTful API 索引库管理 列举索引 创建job_idx索引库 查看索引 删除索引 数据管理 数据插入 数据更新 删除数据 Bu ...

  3. kafka入门(4)-java操作kafka

    kafka入门(4)-java操作kafka 准备工作 创建maven工程 导入Maven Kafka POM依赖 <repositories><!-- 代码库 -->< ...

  4. git config设置用户名_git从安装到多账户操作一套搞定(二)多账户使用

    作者:良知犹存 转载授权以及围观:欢迎添加微信:Allen-Iverson-me-LYN 总述 GIT是当今热门代码管理技术,但是如此火的系统,竟然是大神林纳斯花了两周用C写出来的一个分布式版本控制系 ...

  5. 海皇戟3黑成功,刚入门黑苹果,用5个软件搞定,菜鸟级双系统安装

    之前嫌麻烦,付费在淘宝装的黑苹果,最近系统坏了,又要找人装,求人不如求己.找到一个比较适合菜鸟安装的方法,不用研究config配置,不用到处找驱动,5个软件依次操作,5步搞定 2018-11-24 1 ...

  6. elasticsearch基本操作 --- 使用java操作elasticsearch

    随着大数据的兴起,面对越来越多的数据和越来越复杂的业务场景,系统对后端也提出了更高的要求,尤其是用户体验上,低延迟.快速响应已经成为检验后端程序是否高效很重要的标准,在后端的数据存储框架中,elast ...

  7. redis入门及java操作

    redis 命令可以去菜鸟教程http://www.runoob.com/redis/redis-tutorial.html 或者以下地址去学习http://www.cnblogs.com/huang ...

  8. ffmpeg入门及java操作ffmpeg对视频进行处理

    一.ffmpeg 1.简介 FFmpeg是一个开源免费跨平台的视频和音频流方案,属于自由软件,采用LGPL或GPL许可证(依据你选择的组件).它提供了录制.转换以及流化音视频的完整解决方案.它包含了非 ...

  9. 使用百度API,分分钟搞定身份证正反面图片中的文字识别(Java代码实现)

    今天时间比较宽松,简单学习了一下百度AI开发平台中的身份证中文字识别,10来分钟就搞定了,百度API就是厉害,简单写下,做个备忘. 下载整个项目源码. 一.注册百度账号及新增一个应用,获取百度API所 ...

最新文章

  1. 简单客户端服务器模型(C++、python和go语言示例)
  2. SpringBoot学习系列之一
  3. oracle中lock和latch的用途
  4. CodeForces - 1353F Decreasing Heights(dp)
  5. http:(1):http简介
  6. win10专业版 提供管理员权限才能删除文件夹
  7. 关于OPENCV 访问外部传进来的Mat矩阵元素的问题
  8. 精选32个最新Python实战项目(附源码),拿走就用
  9. 单片机c语言实验报告心得,单片机实习心得体会
  10. 阿里云云呼叫中心——软电话SDK前端接入
  11. Altium Designer(AD)软件使用记录05-PCB叠层设计
  12. Robot Framework(十三):使用RF进行web测试(下)
  13. X99主板2011-3接口E5 CPU一览表
  14. 国外问卷调查该怎么做?入门须知!
  15. matlab 截屏为什么没有呢,录屏没有呀!什么都没有,只有截屏,原来明明有的,现在不知道为什么就突然没有了(手机华为青春版)...
  16. 基因组注释1. 重复序列repeatmasker, trf
  17. 北京“众合天下”连续八年发布中国企业社保白皮书
  18. kcon 黑客大会 github
  19. openwrt中br-lan,eth0,eth0.1,eth0.2 已经 实际网口wan,lan对应的配置
  20. 使用VS2015 VC++第一步 写一个hello world程序

热门文章

  1. SpringBoot整合Security安全框架、控制权限
  2. 多媒体个人计算机能处理什么,多媒体计算机可以处理的信息类型有哪些
  3. 在集群的操作机上执行命令为什么会出现权限被拒绝_如何使用 TDengine 2.0 最新开源的集群功能?
  4. php内核总结_深入理解PHP内核(一)
  5. c# 定位内存快速增长_c#如何避免内存分配瓶颈以提高多线程性能
  6. python sql 日期查询_Python--flask使用 SQLAlchemy查询数据库最近时间段或之前的数据...
  7. 机器学习处理信号分离_[学习笔记]使用机器学习和深度学习处理信号基础知识...
  8. 格兰因果模型可以分析哪些东西_如何系统地学习统计学,指导入门数据分析
  9. html绘制头像原样教程,CSS实例教程:创意CSS3头像展示教程
  10. 电脑开机3秒就重启循环_移动办公神器!电脑包秒变支架、鼠标垫,3合1设计超方便!...