elasticSearch入门到java操作api一套搞定
目录
写在前面
一、下载地址
二、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一套搞定相关推荐
- ElasticSearch入门-搜索(java api)
ElasticSearch入门-搜索(java api) package com.qlyd.searchhelper;import java.util.Map;import net.sf.json.J ...
- Elasticsearch入门(二) API
Elasticsearch入门(二) API VSCode部署 RESTful API 索引库管理 列举索引 创建job_idx索引库 查看索引 删除索引 数据管理 数据插入 数据更新 删除数据 Bu ...
- kafka入门(4)-java操作kafka
kafka入门(4)-java操作kafka 准备工作 创建maven工程 导入Maven Kafka POM依赖 <repositories><!-- 代码库 -->< ...
- git config设置用户名_git从安装到多账户操作一套搞定(二)多账户使用
作者:良知犹存 转载授权以及围观:欢迎添加微信:Allen-Iverson-me-LYN 总述 GIT是当今热门代码管理技术,但是如此火的系统,竟然是大神林纳斯花了两周用C写出来的一个分布式版本控制系 ...
- 海皇戟3黑成功,刚入门黑苹果,用5个软件搞定,菜鸟级双系统安装
之前嫌麻烦,付费在淘宝装的黑苹果,最近系统坏了,又要找人装,求人不如求己.找到一个比较适合菜鸟安装的方法,不用研究config配置,不用到处找驱动,5个软件依次操作,5步搞定 2018-11-24 1 ...
- elasticsearch基本操作 --- 使用java操作elasticsearch
随着大数据的兴起,面对越来越多的数据和越来越复杂的业务场景,系统对后端也提出了更高的要求,尤其是用户体验上,低延迟.快速响应已经成为检验后端程序是否高效很重要的标准,在后端的数据存储框架中,elast ...
- redis入门及java操作
redis 命令可以去菜鸟教程http://www.runoob.com/redis/redis-tutorial.html 或者以下地址去学习http://www.cnblogs.com/huang ...
- ffmpeg入门及java操作ffmpeg对视频进行处理
一.ffmpeg 1.简介 FFmpeg是一个开源免费跨平台的视频和音频流方案,属于自由软件,采用LGPL或GPL许可证(依据你选择的组件).它提供了录制.转换以及流化音视频的完整解决方案.它包含了非 ...
- 使用百度API,分分钟搞定身份证正反面图片中的文字识别(Java代码实现)
今天时间比较宽松,简单学习了一下百度AI开发平台中的身份证中文字识别,10来分钟就搞定了,百度API就是厉害,简单写下,做个备忘. 下载整个项目源码. 一.注册百度账号及新增一个应用,获取百度API所 ...
最新文章
- 简单客户端服务器模型(C++、python和go语言示例)
- SpringBoot学习系列之一
- oracle中lock和latch的用途
- CodeForces - 1353F Decreasing Heights(dp)
- http:(1):http简介
- win10专业版 提供管理员权限才能删除文件夹
- 关于OPENCV 访问外部传进来的Mat矩阵元素的问题
- 精选32个最新Python实战项目(附源码),拿走就用
- 单片机c语言实验报告心得,单片机实习心得体会
- 阿里云云呼叫中心——软电话SDK前端接入
- Altium Designer(AD)软件使用记录05-PCB叠层设计
- Robot Framework(十三):使用RF进行web测试(下)
- X99主板2011-3接口E5 CPU一览表
- 国外问卷调查该怎么做?入门须知!
- matlab 截屏为什么没有呢,录屏没有呀!什么都没有,只有截屏,原来明明有的,现在不知道为什么就突然没有了(手机华为青春版)...
- 基因组注释1. 重复序列repeatmasker, trf
- 北京“众合天下”连续八年发布中国企业社保白皮书
- kcon 黑客大会 github
- openwrt中br-lan,eth0,eth0.1,eth0.2 已经 实际网口wan,lan对应的配置
- 使用VS2015 VC++第一步 写一个hello world程序
热门文章
- SpringBoot整合Security安全框架、控制权限
- 多媒体个人计算机能处理什么,多媒体计算机可以处理的信息类型有哪些
- 在集群的操作机上执行命令为什么会出现权限被拒绝_如何使用 TDengine 2.0 最新开源的集群功能?
- php内核总结_深入理解PHP内核(一)
- c# 定位内存快速增长_c#如何避免内存分配瓶颈以提高多线程性能
- python sql 日期查询_Python--flask使用 SQLAlchemy查询数据库最近时间段或之前的数据...
- 机器学习处理信号分离_[学习笔记]使用机器学习和深度学习处理信号基础知识...
- 格兰因果模型可以分析哪些东西_如何系统地学习统计学,指导入门数据分析
- html绘制头像原样教程,CSS实例教程:创意CSS3头像展示教程
- 电脑开机3秒就重启循环_移动办公神器!电脑包秒变支架、鼠标垫,3合1设计超方便!...