ElasticSearch入门

2023-11-18

文章目录

一、ElasticSearch简介

1、什么是ElasticSearch

       Elaticsearch,简称为es, es是⼀个开源的⾼扩展的分布式全⽂检索引擎,它可以近乎实时的存储、检索数据;本⾝扩展性很好,可以扩展到上百台服务器,处理PB级别的数据。es也使⽤Java开发并使⽤Lucene作为其核⼼来实现所有索引和搜索的功能,但是它的⽬的是通过简单的RESTful API来隐藏Lucene的复杂性,从⽽让全⽂搜索变得简单。
       补充: 什么是全文检索     Lucene的介绍和使用

2、ElasticSearch使用案例

  • 2013年初,GitHub抛弃了Solr,采取ElasticSearch 来做PB级的搜索。 “GitHub使⽤ElasticSearch搜索20TB的数据,包括13亿⽂件和1300亿⾏代码”
  • 维基百科:启动以elasticsearch为基础的核⼼搜索架构
  • SoundCloud:“SoundCloud使⽤ElasticSearch为1.8亿⽤户提供即时⽽精准的⾳乐搜索服务”
  • 百度:百度⽬前⼴泛使⽤ElasticSearch作为⽂本数据分析,采集百度所有服务器上的各类指标数据及⽤户⾃定义数据,通过对各种数据进⾏多维分析展⽰,辅助定位分析实例异常或业务层⾯异常。⽬前覆盖百度内部20多个业务线(包括casio、云分析、⽹盟、预测、⽂库、直达号、钱包、风控等),单集群最⼤100台机器,200个ES节点,每天导⼊30TB+数据
  • 新浪使⽤ES 分析处理32亿条实时⽇志
  • 阿⾥使⽤ES 构建挖财⾃⼰的⽇志采集和分析体系

3、ElasticSearch对⽐Solr

  • Solr 利⽤ Zookeeper 进⾏分布式管理,⽽ Elasticsearch ⾃⾝带有分布式协调管理功能;
  • Solr ⽀持更多格式的数据,⽽ Elasticsearch 仅⽀持json⽂件格式;
  • Solr 官⽅提供的功能更多,⽽ Elasticsearch 本⾝更注重于核⼼功能,⾼级功能多有第三⽅插件提供;
  • Solr 在传统的搜索应⽤中表现好于 Elasticsearch,但在处理实时搜索应⽤时效率明显低于Elasticsearch

二、ElasticSearch相关概念(术语)

1,概述

       Elasticsearch是⾯向⽂档(document oriented)的,这意味着它可以存储整个对象或⽂档(document)。然⽽它不仅仅是存储,还会索引(index)每个⽂档的内容使之可以被搜索。在Elasticsearch中,你可以对⽂档(⽽⾮成⾏成列的数据)进⾏索引、搜索、排序、过滤。Elasticsearch对⽐传统关系型数据库如下:
在这里插入图片描述

2,索引 index

       ⼀个索引就是⼀个拥有⼏分相似特征的⽂档的集合。⽐如说,你可以有⼀个客户数据的索引,另⼀个产品⽬录的索引,还有⼀个订单数据的索引。⼀个索引由⼀个名字来标识(必须全部是⼩写字母的),并且当我们要对对应于这个索引中的⽂档进⾏索引、搜索、更新和删除的时候,都要使⽤到这个名字。在⼀个集群中,可以定义任意多的索引。

3,类型 type

       在⼀个索引中,你可以定义⼀种或多种类型。⼀个类型是你的索引的⼀个逻辑上的分类/分区,其语义完全由你来定。通常,会为具有⼀组共同字段的⽂档定义⼀个类型。⽐如说,我们假设你运营⼀个博客平台并且将你所有的数据存储到⼀个索引中。在这个索引中,你可以为⽤户数据定义⼀个类型,为博客数据定义另⼀个类型,当然,也可以为评论数据定义另⼀个类型。

4,字段 Field

       相当于是数据表的字段,对⽂档数据根据不同属性进⾏的分类标识

5,映射 mapping

       mapping是处理数据的⽅式和规则⽅⾯做⼀些限制,如某个字段的数据类型、默认值、分析器、是否被索引等等,这些都是映射⾥⾯可以设置的,其它就是处理es⾥⾯数据的⼀些使⽤规则设置也叫做映射,按着最优规则处理数据对性能提⾼很⼤,因此才需要建⽴映射,并且需要思考如何建⽴映射才能对性能更好。

6,⽂档 document

       ⼀个⽂档是⼀个可被索引的基础信息单元。⽐如,你可以拥有某⼀个客户的⽂档,某⼀个产品的⼀个⽂档,当然,也可以拥有某个订单的⼀个⽂档。⽂档以JSON(Javascript Object Notation)格式来表⽰,⽽JSON是⼀个到处存在的互联⽹数据交互格式。
       在⼀个index/type⾥⾯,你可以存储任意多的⽂档。注意,尽管⼀个⽂档,物理上存在于⼀个索引之中,⽂档必须被索引/赋予⼀个索引的type。

7,接近实时 NRT

       Elasticsearch是⼀个接近实时的搜索平台。这意味着,从索引⼀个⽂档直到这个⽂档能够被搜索到有⼀个轻微的延迟(通常是1秒以内)

8,集群 cluster

       ⼀个集群就是由⼀个或多个节点组织在⼀起,它们共同持有整个的数据,并⼀起提供索引和搜索功能。⼀个集群由⼀个唯⼀的名字标识,这个名字默认就是“elasticsearch”。这个名字是重要的,因为⼀个节点只能通过指定某个集群的名字,来加⼊这个集群

9,节点 node

       ⼀个节点是集群中的⼀个服务器,作为集群的⼀部分,它存储数据,参与集群的索引和搜索功能。和集群类似,⼀个节点也是由⼀个名字来标识的,默认情况下,这个名字是⼀个随机的漫威漫画⾓⾊的名字,这个名字会在启动的时候赋予节点。这个名字对于管理⼯作来说挺重要的,因为在这个管理过程中,你会去确定⽹络中的哪些服务器对应于Elasticsearch集群中的哪些节点。
       ⼀个节点可以通过配置集群名称的⽅式来加⼊⼀个指定的集群。默认情况下,每个节点都会被安排加⼊到⼀个叫做“elasticsearch”的集群中,这意味着,如果你在你的⽹络中启动了若⼲个节点,并假定它们能够相互发现彼此,它们将会⾃动地形成并加⼊到⼀个叫做“elasticsearch”的集群中。
       在⼀个集群⾥,只要你想,可以拥有任意多个节点。⽽且,如果当前你的⽹络中没有运⾏任何Elasticsearch节点时,这时启动⼀个节点,会默认创建并加⼊⼀个叫做“elasticsearch”的集群。

10,分⽚和复制 shards&replicas

       当⼀个索引需要存储的数据超出单个结点硬件限制的最大数据时,⽐如,⼀个具有10亿⽂档的索引占据1TB的磁盘空间,⽽任⼀节点都没有这样⼤的磁盘空间;或者单个节点处理搜索请求,响应太慢时。该如何解决?
       为了解决这个问题,Elasticsearch提供了将索引划分成多份的能⼒,这些份就叫做分⽚。当你创建⼀个索引的时候,你可以指定你想要的分⽚的数量。每个分⽚本⾝也是⼀个功能完善并且独⽴的“索引”,这个“索引”可以被放置到集群中的任何节点上。分⽚很重要,主要有两⽅⾯的原因:

              (1)允许你⽔平分割/扩展你的内容容量。
              (2)允许你在分⽚(位于多个节点上)之上进⾏分布式的、并⾏的操作,进⽽提⾼性能/吞吐量。

       ⾄于⼀个分⽚怎样分布,它的⽂档怎样聚合回搜索请求,是完全由Elasticsearch管理的,对于作为⽤户的你来说,这些都是透明的。
       在⼀个⽹络/云的环境⾥,失败随时都可能发⽣,在某个分⽚/节点不知怎么的就处于离线状态,或者由于任何原因消失了,这种情况下,有⼀个故障转移机制是⾮常有⽤并且是强烈推荐的。为此⽬的,Elasticsearch允许你创建分⽚的⼀份或多份拷贝,这些拷贝叫做复制分⽚,或者直接叫复制。
       复制之所以重要,有两个主要原因: 在分⽚/节点失败的情况下,提供了⾼可⽤性。因为这个原因,注意到复制分⽚从不与原/主要(original/primary)分⽚置于同⼀节点上是⾮常重要的。l另外,复制可以扩展你的搜索量/吞吐量,因为搜索可以在所有的复制上并⾏运⾏。
       总之,每个索引可以被分成多个分⽚。⼀个索引也可以被复制0次(意思是没有复制)或多次。⼀旦复制了,每个索引就有了主分⽚(作为复制源的原来的分⽚)和复制分⽚(主分⽚的拷贝)之别。分⽚和复制的数量可以在索引创建的时候指定。在索引创建之后,你可以在任何时候动态地改变复制的数量,但是你事后不能改变分⽚的数量。
       默认情况下,Elasticsearch中的每个索引被分⽚5个主分⽚和1个复制,这意味着,如果你的集群中⾄少有两个节点,你的索引将会有5个主分⽚和另外5个复制分⽚(1个完全拷贝),这样的话每个索引总共就有10个分⽚。
在这里插入图片描述

三、ElasticSearch使用

1,Elasticsearch 安装

参考链接:es下载安装
也可自寻参考网上教程

2,Elasticsearch 客户端操作

2.1,elasticsearch-head安装

参考链接:elasticsearch-head安装和使用
如若es相关软件或插件的安装使用出现问题请自寻参考网上教程

2.2,使⽤Postman⼯具进⾏Restful接⼜访问

2.2.1,ElasticSearch 的接口语法

在这里插入图片描述

2.2.2,创建索引 index 和映射 mapping

请求url:

PUT 192.168.220.100:9200/blog1

请求体:

{
	"mappings": {
		"article": {
			"properties": {
				"id": {
					"type": "long",
					"store": true,
					"index":"not_analyzed"
				},
				"title": {
					"type": "text",
					"store": true,
					"index":"analyzed",
					"analyzer":"standard"
				},
				"content": {
					"type": "text",
					"store": true,
					"index":"analyzed",
					"analyzer":"standard"
				}
			}
		}
	}
}

elasticsearch-head查看:
在这里插入图片描述

2.2.3,创建索引后设置 Mapping

       我们可以在创建索引时设置mapping信息,当然也可以先创建索引然后再设置mapping。在上⼀个步骤中创建索引时不设置请求体,即不设置mapping信息,直接使⽤put⽅法创建⼀个索引,然后使用post方法来提交mapping信息。

请求的url:

POST http://192.168.220.100:9200/blog2/hello/_mapping

请求体:

{
	"hello": {
		"properties": {
			"id":{
				"type":"long",
				"store":true
			},
			"title":{
				"type":"text",
				"store":true,
				"index":true,
				"analyzer":"standard"
			},
			"content":{
				"type":"text",
				"store":true,
				"index":true,
				"analyzer":"standard"
			}
		}
	}
}
2.2.4,删除索引 index

请求url:

DELETE 192.168.220.100:9200/blog1

elasticsearch-head查看:
在这里插入图片描述

2.2.5,创建⽂档 document

请求url:

POST 192.168.220.100:9200/blog1/article/1

请求体:

{
	"id":1,
	"title":"ElasticSearch是⼀个基于Lucene的搜索服务器",
	"content":"它提供了⼀个分布式多⽤户能⼒的全⽂搜索引擎,基于RESTful web接⼝。
	Elasticsearch是⽤Java开发的,并作为Apache许可条款下的开放源码发布,是当前流⾏的企业级搜
	索引擎。设计⽤于云计算中,能够达到实时搜索,稳定,可靠,快速,安装使⽤⽅便。"
}

elasticsearch-head查看:
在这里插入图片描述

2.2.6,修改⽂档 document

修改文档其实就是添加一个id相同的文档

请求url:

POST 192.168.220.100:9200/blog1/article/1

请求体:

{
	"id":1,
	"title":"【修改】ElasticSearch是⼀个基于Lucene的搜索服务器",
	"content":"【修改】它提供了⼀个分布式多⽤户能⼒的全⽂搜索引擎,基于RESTful web接⼝。
	Elasticsearch是⽤Java开发的,并作为Apache许可条款下的开放源码发布,是当前流⾏的企业级搜
	索引擎。设计⽤于云计算中,能够达到实时搜索,稳定,可靠,快速,安装使⽤⽅便。"
}

elasticsearch-head查看:
在这里插入图片描述

2.2.7,删除⽂档 document

请求url:

DELETE 192.168.220.100:9200/blog1/article/1

2.2.8,查询⽂档 - 根据 id 查询

请求url:

GET 192.168.220.100:9200/blog1/article/1

elasticsearch-head查看:
在这里插入图片描述

2.2.9,查询⽂档 -querystring 查询 和 term 查询

重新添加文档之后进行查询:
请求url:

POST 192.168.220.100:9200/blog1/article/_search

分别发送以下三个请求体:
请求体1:

{
	"query": {
		"query_string": {
			"default_field": "title",
			"query": "搜索服务器"
		}
	}
}

请求体2:

{
	"query": {
		"query_string": {
			"default_field": "title",
			"query": "钢索"
		}
	}
}

请求体3:

{
	"query": {
		"term": {
			"title": "搜索"
		}
	}
}

结果:请求1和请求2能查询到,而请求3查询不到

原因:在创建索引时,声明了各字段以标准分词器进行分词;对于中文,标准分词器会将每一个字作为一个词;每添加一个文档(记录),便会通过分词器对其建立索引。当通过query_string的方式查询时,会通过标准分词器分词查询,所以一旦根据查询体中的某个字查询到便可;而当通过term的方式查询时,不会对查询体分词查询,此时查询体匹配不到索引中的词,所以查询不到。

我们希望,在建立索引时,使用符合中文语义的分词器进行分词;同样,在查询时,使用该分词器对查询体进行分词查询。这时,就需要用到IK分词器。

3,IK分词器

3.1,IK分词器简介

       IKAnalyzer是⼀个开源的,基于java语⾔开发的轻量级的中⽂分词⼯具包。从2006年12⽉推出1.0版开始,IKAnalyzer已经推出 了3个⼤版本。最初,它是以开源项⽬Lucene为应⽤主体的,结合词典分词和⽂法分析算法的中⽂分词组件。新版本的IKAnalyzer3.0则发展为 ⾯向Java的公⽤分词组件,独⽴于Lucene项⽬,同时提供了对Lucene的默认优化实现。

IK分词器3.0的特性如下:

  • 采⽤了特有的“正向迭代最细粒度切分算法“,具有60万字/秒的⾼速处理能⼒。
  • 采⽤了多⼦处理器分析模式,⽀持:英⽂字母(IP地址、Email、URL)、数字(⽇期,常⽤中⽂数量词,罗马数字,科学计数法),中⽂词汇(姓名、地名处理)等分词处理。
  • 对中英联合⽀持不是很好,在这⽅⾯的处理⽐较⿇烦.需再做⼀次查询,同时是⽀持个⼈词条的优化的词典存储,更⼩的内存占⽤。
  • ⽀持⽤户词典扩展定义。
  • 针对Lucene全⽂检索优化的查询分析器IKQueryParser;采⽤歧义分析算法优化查询关键字的搜索排列组合,能极⼤的提⾼Lucene检索的命中率。

3.2,IK分词器安装使用

ik分词器版本需要与es版本一致
参考链接:ik分词器安装

使用示例(创建索引时使用):
在这里插入图片描述

ik_max_word:会将⽂本做最细粒度的拆分

  • ⽐如会将“中华⼈民共和国⼈民⼤会堂”拆分为“中华⼈民共和国、中华⼈民、中华、华⼈、⼈民共和国、⼈民、共和国、⼤会堂、⼤会、会堂等词语。

ik_smart:会做最粗粒度的拆分

  • ⽐如会将“中华⼈民共和国⼈民⼤会堂”拆分为中华⼈民共和国、⼈民⼤会堂。

四、Kibana使⽤-掌握DSL语句

1,Kibana简介

       我们上⾯使⽤的是elasticsearch-head插件实现数据查找的,但是elasticsearch-head的功能⽐较单⼀,我们这⾥需要⼀个更专业的⼯具实现对⽇志的实时分析,也就是我们接下来要讲的kibana。
       Kibana 是⼀款开源的数据分析和可视化平台,它是 Elastic Stack 成员之⼀,设计⽤于和 Elasticsearch协作。您可以使⽤ Kibana 对 Elasticsearch 索引中的数据进⾏搜索、查看、交互操作。您可以很⽅便的利⽤图表、表格及地图对数据进⾏多元化的分析和呈现。
       Kibana 可以使⼤数据通俗易懂。它很简单,基于浏览器的界⾯便于您快速创建和分享动态数据仪表板来追踪 Elasticsearch 的实时数据变化。
       搭建 Kibana ⾮常简单。您可以分分钟完成 Kibana 的安装并开始探索 Elasticsearch 的索引数据 — 没有代码、不需要额外的基础设施。

2,Kibana下载安装

参考链接:Kibana安装

3,Kibana使用

3.1,配置索引

要使⽤Kibana,您必须⾄少配置⼀个索引。索引⽤于标识Elasticsearch索引以运⾏搜索和分析。它们还⽤于配置字段。
在这里插入图片描述
我们修改索引名称的匹配⽅式即可,下⾯2个选项不⽤勾选。点击create,会展⽰出当前配置的索引的域信息,如下图:
在这里插入图片描述
域的每个标题选项分别代表如下意思:
在这里插入图片描述

3.2,数据搜索

Discover为数据搜索部分,可以对⽇志信息进⾏搜索操作。
在这里插入图片描述
可以使⽤Discover实现数据搜索过滤和搜索条件显⽰以及关键词搜索,如下图:在这里插入图片描述

3.3,DSL 语句使用

3.3.1,Query DSL结构化查询介绍

       Query DSL是⼀个Java开源框架⽤于构建类型安全的SQL查询语句。采⽤API代替传统的拼接字符串来构造查询语句。⽬前Querydsl⽀持的平台包括JPA,JDO,SQL,Java Collections,RDF,Lucene,Hibernate Search。elasticsearch提供了⼀整套基于JSON的DSL语⾔来定义查询。

3.3.2,查询所有索引

DSL语句:

GET /_cat/indices?v

结果如下:
在这里插入图片描述

3.3.3,删除某个索引

DSL语句:

DELETE /skuinfo

结果如下:
在这里插入图片描述

3.3.4,新增索引

DSL语句:

PUT /user

结果如下:
在这里插入图片描述

3.3.5,创建映射

DSL语句:

PUT /user/userinfo/_mapping
{
	"properties": {
		"name":{
			"type": "text",
			"analyzer": "ik_smart",
			"search_analyzer": "ik_smart"
		},
		"city":{
			"type": "text",
			"analyzer": "ik_smart",
			"search_analyzer": "ik_smart"
		},
		"age":{
			"type": "long"
		},
		"description":{
			"type": "text",
			"analyzer": "ik_smart",
			"search_analyzer": "ik_smart"
		}
	}
}
3.3.6,新增⽂档数据

DSL语句:

PUT /user/userinfo/1
{
	"name":"李四",
	"age":22,
	"city":"深圳",
	"description":"李四来⾃湖北武汉!"
}
#新增⽂档数据 id=4
PUT /user/userinfo/4
{
	"name":"张三丰",
	"age":66,
	"city":"武汉",
	"description":"在武汉读书,家在武汉!"
}
#新增⽂档数据 id=5
PUT /user/userinfo/5
{
	"name":"赵⼦⻰",
	"age":77,
	"city":"⼴州",
	"description":"赵⼦⻰来⾃深圳宝安,但是在⼴州⼯作!",
	"address":"⼴东省茂名市" #该文档多添加一个字段
}
3.3.7,修改⽂档数据

(1)替换操作
更新数据可以使⽤之前的增加操作,这种操作会将整个数据替换掉。
DSL语句:

#更新数据,id=4
PUT /user/userinfo/4
{
	"name":"张三丰",
	"description":"在武汉读书,家在武汉!在深圳⼯作!"
}

效果如下:
在这里插入图片描述
使⽤GET命令查看:GET /user/userinfo/4
效果如下:
在这里插入图片描述
(2)更新操作
我们先使⽤下⾯命令恢复数据:

#恢复⽂档数据 id=4
PUT /user/userinfo/4
{
	"name":"张三丰",
	"age":66,
	"city":"武汉",
	"description":"在武汉读书,家在武汉!"
}

使⽤POST更新某个列的数据

#使⽤POST更新某个域的数据
POST /user/userinfo/4/_update
{
	"doc":{   #单独更改部分字段必须有
		"name":"张三丰",
		"description":"在武汉读书,家在武汉!在深圳⼯作!"
	}
}

效果如下:
在这里插入图片描述
使⽤GET命令查看:GET /user/userinfo/4
在这里插入图片描述

3.3.8,删除Document

DELETE /user/userinfo/7

3.3.9,查询所有数据

GET /user/_search

3.3.10,根据ID查询

GET /user/userinfo/2

3.3.11,Sort排序

DSL语句:

#搜索排序
GET /user/_search
{
	"query":{
		"match_all": {}
	},
	"sort":{
		"age":{
			"order":"desc"
		}
	}
}

效果如下:
在这里插入图片描述

3.3.12,分页查询

DSL语句:

#分⻚实现
GET /user/_search
{
	"query":{
		"match_all": {}
	},
	"sort":{
		"age":{
			"order":"desc"
		}
	},
	"from": 0,
	"size": 2
}

解释:from:从下标N的记录开始查询;size:每页显⽰条数
效果如下:
在这里插入图片描述

3.3.13,term、match、match_phrase、query_string查询

参考链接:term、match、match_phrase、query_string查询的区别

3.3.14,range 查询

range过滤允许我们按照指定范围查找⼀批数据。例如我们查询年龄范围

#-range 范围过滤
#gt表示> gte表示=>
#lt表示< lte表示<=
GET _search
{
	"query":{
		"range": {
			"age": {
				"gte": 30,
				"lte": 57
			}
		}
	}
}

效果如下:
在这里插入图片描述

3.3.15,exists查询

exists 过滤可以⽤于查找拥有某个域的数据

#搜索 exists:是指包含某个域的数据检索
GET _search
{
	"query": {
		"exists":{
			"field":"address"
		}
	}
}

效果如下:
在这里插入图片描述

3.3.16,bool 查询

bool 可以⽤来合并多个条件查询结果的布尔逻辑,它包含以下操作符:

  • must : 多个查询条件的完全匹配,相当于 and。
  • must_not : 多个查询条件的相反匹配,相当于 not。
  • should : ⾄少有⼀个查询条件匹配, 相当于 or。

这些参数可以分别继承⼀个过滤条件或者⼀个过滤条件的数组:

#过滤搜索 bool
#must : 多个查询条件的完全匹配,相当于 and。
#must_not : 多个查询条件的相反匹配,相当于 not。
#should : ⾄少有⼀个查询条件匹配, 相当于 or。
GET _search
{
	"query": {
		"bool": {
			"must": [
				{
					"term": {
						"city": {
							"value": "深圳"
						}
					}
				},
				{
					"range":{
						"age":{
							"gte":20,
							"lte":99
						}
					}
				}
			]
		}
	}
}

效果如下:
在这里插入图片描述

3.3.17,match_all查询

可以查询到所有⽂档,是没有查询条件下的默认语句。

#查询所有 match_all
GET _search
{
	"query": {
		"match_all": {}
	}
}
3.3.18,prefix 查询

以什么字符开头的,可以更简单地⽤ prefix ,例如查询所有以张开始的⽤户描述

#前缀匹配 prefix
GET _search
{
	"query": {
		"prefix": {
			"name": {
				"value": "赵"
			}
		}
	}
}
3.3.19,multi_match 查询

multi_match查询允许你做match查询的基础上同时搜索多个字段,在多个字段中同时查⼀个

#多个域匹配搜索
GET _search
{
	"query": {
		"multi_match": {
			"query": "深圳",
			"fields": [
				"city",
				"description"
			]
		}
	}
}

效果如下:
在这里插入图片描述

3.3.20,filter
#过滤-range 范围过滤
#gt表示> gte表示=>
#lt表示< lte表示<=
GET _search
{
	"query": {
		"bool": {
			"must": [
				{"match": {
					"city": "深圳武汉"
				}}
			],
			"filter": {
				"range": {
					"age": {
						"gte": 20,
						"lte": 60
					}
				}
			}
		}
	}
}

filter只能用在bool下

因为过滤可以使⽤缓存,同时不计算分数,通常的规则是,使⽤查询(query)语句来进⾏ 全⽂ 搜索或者其它任何需要影响 相关性得分 的搜索。除此以外的情况都使⽤过滤(filters)

五、ElasticSearch编程操作

1,创建⼯程,导⼊坐标

<dependency>
	<groupId>org.elasticsearch</groupId>
	<artifactId>elasticsearch</artifactId>
	<version>5.6.8</version>
</dependency>
<dependency>
	<groupId>org.elasticsearch.client</groupId>
	<artifactId>transport</artifactId>
	<version>5.6.8</version>
</dependency>

2,创建索引

@Test
//创建索引
public void test1() throws Exception{
	//1.设置加入的集群
	Settings settings = Settings.builder().put("cluster.name", "myelasticsearch").build();
	//2.创建Client连接对象
	TransportClient client = new PreBuiltTransportClient(settings)
							.addTransportAddress(newInetSocketTransportAddress(InetAddress.getByName("192.168.220.100"), 9300));
	//3.创建名称为blog2的索引
	client.admin().indices().prepareCreate("blog2").get();
	//4.释放资源
	client.close();
}

elasticsearch-head查看:
在这里插入图片描述
在这里插入图片描述

3,创建映射mapping

代码如下:

@Test
//创建映射
public void test3() throws Exception{
	// 创建Client连接对象
	Settings settings = Settings.builder().put("cluster.name", "my-elasticsearch").build();
	TransportClient client = new PreBuiltTransportClient(settings)
							.addTransportAddress(newInetSocketTransportAddress(InetAddress.getByName("127.0.0.1"), 9300));
	 //创建映射的json数据
	 XContentBuilder builder = XContentFactory.jsonBuilder()
								.startObject()
								.startObject("article")
								.startObject("properties")
								.startObject("id")
								.field("type", "integer").field("store", "yes")
								.endObject()
								.startObject("title")
								.field("type", "string").field("store", "yes").field("analyzer",
								"ik_smart")
								.endObject()
								.startObject("content")
								.field("type", "string").field("store", "yes").field("analyzer",
								"ik_smart")
								.endObject()
								.endObject()
								.endObject()
								.endObject();
	// 创建映射
	PutMappingRequest mapping = Requests.putMappingRequest("blog2").type("article").source(builder);
	client.admin().indices().putMapping(mapping).get();
	//释放资源
	client.close();
}

elasticsearch-head查看:
在这里插入图片描述
在这里插入图片描述

4,建⽴⽂档document

4.1,通过 XContentBuilder

代码如下:

@Test
public void testAddDocument() throws Exception {
	//创建⼀个client对象
	// 创建Client连接对象
	Settings settings = Settings.builder().put("cluster.name", "my-elasticsearch").build();
	TransportClient client = new PreBuiltTransportClient(settings)
							.addTransportAddress(newInetSocketTransportAddress(InetAddress.getByName("127.0.0.1"), 9300));
	//创建⽂档的json数据
	XContentBuilder builder = XContentFactory.jsonBuilder()
							  .startObject()
						      .field("id",2l)
							  .field("title","北⽅⼊秋速度明显加快 多地降温幅度最多可达10度22222")
							  .field("content", "阿联酋⼀架客机在纽约机场被隔离 10名乘客病倒")
							  .endObject();
	//把⽂档对象添加到索引库
	client.prepareIndex()
		   //设置索引名称
		   .setIndex("index_hello")
		   //设置type
		   .setType("article")
		   //设置⽂档的id,如果不设置的话⾃动的⽣成⼀个id
		   .setId("2")
		   //设置⽂档信息
		   .setSource(builder)
		   //执⾏操作
		   .get();
	//关闭客户端
	client.close();
}

elasticsearch-head查看:
在这里插入图片描述

4.2,使⽤ Jackson 转换实体

(1)创建Article实体

public class Article {
	private Integer id;
	private String title;
	private String content;
	getter/setter...
}

(2)添加jackson坐标

<dependency>
	<groupId>com.fasterxml.jackson.core</groupId>
	<artifactId>jackson-core</artifactId>
	<version>2.8.1</version>
</dependency>
<dependency>
	<groupId>com.fasterxml.jackson.core</groupId>
	<artifactId>jackson-databind</artifactId>
	<version>2.8.1</version>
</dependency>
<dependency>
	<groupId>com.fasterxml.jackson.core</groupId>
	<artifactId>jackson-annotations</artifactId>
	<version>2.8.1</version>
</dependency>

(3)代码实现

@Test
public void testAddDocument2() throws Exception {
	//创建⼀个Article对象
	Article article = new Article();
	//设置对象的属性
	article.setId(3l);
	article.setTitle("MH370坠毁在柬埔寨密林?中国⼀公司调⼗颗卫星去拍摄");
	article.setContent("警惕荒唐的死亡游戏!俄15岁少年输掉游戏后⽤电锯⾃杀");
	//把article对象转换成json格式的字符串。
	ObjectMapper objectMapper = new ObjectMapper();
	String jsonDocument = objectMapper.writeValueAsString(article);
	System.out.println(jsonDocument);
	//使⽤client对象把⽂档写⼊索引库
	client.prepareIndex("index_hello","article", "3")
		  .setSource(jsonDocument, XContentType.JSON)
		  .get();
	//关闭客户端
	client.close();
}

elasticsearch-head查看:
在这里插入图片描述

5,查询⽂档操作

       通过API代码可以实现所有能通过restful请求和DLS语句完成的查询操作,都是类似的;由于内容过多,这里我只演示term查询和query_string查询,其余请自行查阅文档

(1)termQuery

@Test
public void testQueryByTerm() throws Exception {
	//创建⼀个QueryBuilder对象
	//参数1:要搜索的字段
	//参数2:要搜索的关键词
	QueryBuilder queryBuilder = QueryBuilders.termQuery("title", "美丽的⼥护⼠");
	//执⾏查询
	SearchResponse searchResponse = client.prepareSearch("index_hello")
										  .setTypes("article")
										  .setQuery(queryBuilder)
										  .get();
	//取查询结果
	SearchHits searchHits = searchResponse.getHits();
	//取查询结果的总记录数
	System.out.println("查询结果总记录数:" + searchHits.getTotalHits());
	//查询结果列表
	Iterator<SearchHit> iterator = searchHits.iterator();
	while(iterator.hasNext()) {
		SearchHit searchHit = iterator.next();
		//打印⽂档对象,以json格式输出
		System.out.println(searchHit.getSourceAsString());
		//取⽂档的属性
		System.out.println("-----------⽂档的属性");
		Map<String, Object> document = searchHit.getSource();
		System.out.println(document.get("id"));
		System.out.println(document.get("title"));
		System.out.println(document.get("content"));
	}
	//关闭client
	client.close();
}

(2)QueryString

@Test
public void testQueryByQueryString() throws Exception {
	//创建⼀个QueryBuilder对象
	//参数1:要搜索的字段
	//参数2:要搜索的关键词
	QueryBuilder queryBuilder = QueryBuilders.queryStringQuery("美丽的⼥护⼠").defaultField("title");
	//执⾏查询
	SearchResponse searchResponse = client.prepareSearch("index_hello")
										  .setTypes("article")
										  .setQuery(queryBuilder)
										  .get();
	//取查询结果
	SearchHits searchHits = searchResponse.getHits();
	//取查询结果的总记录数
	System.out.println("查询结果总记录数:" + searchHits.getTotalHits());
	//查询结果列表
	Iterator<SearchHit> iterator = searchHits.iterator();
	while(iterator.hasNext()) {
		SearchHit searchHit = iterator.next();
		//打印⽂档对象,以json格式输出
		System.out.println(searchHit.getSourceAsString());
		//取⽂档的属性
		System.out.println("-----------⽂档的属性");
		Map<String, Object> document = searchHit.getSource();
		System.out.println(document.get("id"));
		System.out.println(document.get("title"));
		System.out.println(document.get("content"));
	}
	//关闭client
	client.close();
}

6,查询结果高亮操作

6.1,什么是高亮显示

在进⾏关键字搜索时,搜索出的内容中的关键字会显⽰不同的颜⾊,称之为⾼亮。比如我在京东商城搜索笔记本:
在这里插入图片描述

6.2,高亮显示的 html 分析

通过开发者⼯具查看⾼亮数据的html代码实现:

在这里插入图片描述
ElasticSearch可以对查询出的内容中关键字部分进⾏标签和样式的设置,但是你需要告诉ElasticSearch使⽤什么标签对⾼亮关键字进⾏包裹

6.3,高亮显示代码实现

@Test
public void highlightSearchTest() throws Exception {
	QueryBuilder queryBuilder = QueryBuilders.multiMatchQuery("北京市⺠","title", "content");
	HighlightBuilder highlightBuilder = new HighlightBuilder();
	highlightBuilder.field("title").field("content");
	highlightBuilder.preTags("<em>");
	highlightBuilder.postTags("</em>");
	//执⾏查询
	SearchResponse searchResponse = client.prepareSearch("index_hello")
										  .setTypes("article")
										  .setQuery(queryBuilder)
										  //设置⾼亮信息
										  .highlighter(highlightBuilder)
										  .get();
	//取查询结果
	SearchHits searchHits = searchResponse.getHits();
	//取查询结果的总记录数
	System.out.println("查询结果总记录数:" + searchHits.getTotalHits());
	//查询结果列表
	Iterator<SearchHit> iterator = searchHits.iterator();
	while(iterator.hasNext()) {
		SearchHit searchHit = iterator.next();
		//取⽂档的属性
		System.out.println("-----------⽂档的属性");
		Map<String, Object> document = searchHit.getSource();
		System.out.println(document.get("id"));
		System.out.println(document.get("title"));
		System.out.println(document.get("content"));
		System.out.println("************⾼亮结果");
		Map<String, HighlightField> highlightFields = searchHit.getHighlightFields();
		// //取title⾼亮显示的结果
		if (highlightFields.size() <=0) continue;
		for (Map.Entry<String, HighlightField> entry : highlightFields.entrySet()) {
			System.out.println(entry.getKey() + ":\t" + Arrays.toString(entry.getValue().getFragments()));
		}
	}
	//关闭client
	client.close();
}

运行如下:
在这里插入图片描述

六、Spring Data ElasticSearch

使用原生API代码来操作es过于复杂,可以使用Spring Data ElasticSearch框架来简化开发

1,简介

有关Spring Data 和 JPA 的知识请自行百度

(1)Spring Data

       Spring Data是⼀个⽤于简化数据库访问,并⽀持云服务的开源框架。其主要⽬标是使得对数据的访问变得⽅便快捷,并⽀持map-reduce框架和云计算数据服务。 Spring Data可以极⼤的简化JPA的写法,可以在⼏乎不⽤写实现的情况下,实现对数据的访问和操作。除了CRUD外,还包括如分页、排序等⼀些常⽤的功能。
       Spring Data常⽤的功能模块如下:
在这里插入图片描述
在这里插入图片描述
(2)Spring Data ElasticSearch

       Spring Data ElasticSearch 基于 spring data API 简化 elasticSearch操作,将原始操作elasticSearch的客户端API进⾏封装 。Spring Data为Elasticsearch项⽬提供集成搜索引擎。

2,入门案例

(1)导⼊Spring Data ElasticSearch坐标

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
	https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.1.16.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.example</groupId>
	<artifactId>demo</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>demo</name>
	<description>Demo project for Spring Boot</description>
	<properties>
		<java.version>1.8</java.version>
	</properties>
	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
			</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>
	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>
</project>

(2)yml配置文件

spring:
	data:
		elasticsearch:
			cluster-name: my-elasticsearch
			cluster-nodes: 192.168.220.100:9300

(3)编写实体Article

@Document(indexName = "lxs_blog", type = "article")
public class Article {
	@Id
	@Field(type = FieldType.Long, store = true)
	private long id;
	@Field(type = FieldType.Text, store = true, analyzer = "ik_smart")
	private String title;
	@Field(type = FieldType.Text, store = true, analyzer = "ik_smart")
	private String content;
	...
}

(4)编写Dao

⽅法命名规则查询的基本语法findBy + 属性 + 关键词 + 连接符

在这里插入图片描述

package com.example.demo.repositories;
import com.example.demo.entity.Article;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
import java.util.List;
public interface ArticleRepository extends ElasticsearchRepository<Article,Long> {
}

(5)测试

@Autowired
private ArticleRepository articleRepository;
@Autowired
private ElasticsearchTemplate template;

@Test
public void createIndex() throws Exception {
	//创建索引,并配置映射关系
	template.createIndex(Article.class);
	//配置映射关系
	//template.putMapping(Article.class);
}

@Test
public void addDocument() throws Exception {
	for (int i = 10; i <= 20; i++) {
		//创建⼀个Article对象
		Article article = new Article();
		article.setId(i);
		article.setTitle("⼥护⼠路遇昏迷男⼦跪地抢救:救⼈是职责更是本能" + i);
		article.setContent("这是⼀个美丽的⼥护⼠妹妹" + i);
		//把⽂档写⼊索引库
		articleRepository.save(article);
	}
}
@Test
public void deleteDocumentById() throws Exception {
	// articleRepository.deleteById(1l);
	//全部删除
	articleRepository.deleteAll();
}
@Test
public void findAll() throws Exception {
	Iterable<Article> articles = articleRepository.findAll();
	articles.forEach(a-> System.out.println(a));
}
@Test
public void testFindById() throws Exception {
	Optional<Article> optional = articleRepository.findById(10l);
	Article article = optional.get();
	System.out.println(article);
}

相关方法有很多,请自行测试

3,聚合查询案例

聚合查询相关知识请参考链接:es聚合分析

(1)实体类

@Document(indexName = "car_index", type = "car")
public class Car {
	@Id
	@Field(type = FieldType.Long, store = true)
	private Long id;
	@Field(type = FieldType.Text, store = true, analyzer = "ik_smart")
	private String name;
	@Field(type = FieldType.Text, store = true, analyzer = "ik_smart",fielddata = true)
	private String color;
	@Field(type = FieldType.Text, store = true, analyzer = "ik_smart",fielddata = true)
	private String brand;
	@Field(type = FieldType.Double, store = true)
	private Double price;
	...
}

(2)Dao接口

package com.lxs.esdemo2.dao;
import com.lxs.esdemo2.domain.Article;
import com.lxs.esdemo2.domain.Car;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
public interface CarDao extends ElasticsearchRepository<Car, Long> {
}

(3)初始化索引库

@Autowired
private CarDao carDao;

@Test
public void initIndex() {
	carDao.save(new Car(1l, "⽐亚迪A1", "红⾊", "⽐亚迪", 50000d));
	carDao.save(new Car(2l, "⽐亚迪A2", "⽩⾊", "⽐亚迪", 70000d));
	carDao.save(new Car(3l, "⽐亚迪A3", "⽩⾊", "⽐亚迪", 80000d));
	carDao.save(new Car(4l, "⽐亚迪A4", "红⾊", "⽐亚迪", 60000d));
	carDao.save(new Car(5l, "⽐亚迪A5", "红⾊", "⽐亚迪", 90000d));
	carDao.save(new Car(6l, "宝⻢A1", "红⾊", "宝⻢", 10000d));
	carDao.save(new Car(7l, "宝⻢A2", "⿊⾊", "宝⻢", 20000d));
	carDao.save(new Car(8l, "宝⻢A3", "⿊⾊", "宝⻢", 30000d));
	carDao.save(new Car(9l, "宝⻢A4", "红⾊", "宝⻢", 40000d));
	carDao.save(new Car(10l, "宝⻢A5", "红⾊", "宝⻢", 50000d));
	carDao.save(new Car(11l, "奔驰A1", "红⾊", "奔驰", 10000d));
	carDao.save(new Car(12l, "奔驰A2", "⿊⾊", "奔驰", 20000d));
	carDao.save(new Car(13l, "奔驰A3", "⿊⾊", "奔驰", 30000d));
	carDao.save(new Car(14l, "奔驰A4", "红⾊", "奔驰", 40000d));
	carDao.save(new Car(15l, "奔驰A5", "红⾊", "奔驰", 50000d));
}

(4)代码实例1,按颜色分组

@Test
public void testQuerySelfAggs(){
	//查询条件的构建器
	NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder().withQuery(QueryBuilders.matchAllQuery());
	//排除所有的字段查询,
	queryBuilder.withSourceFilter(new FetchSourceFilter(new String[]{},null));
	//添加聚合条件,按颜色分组
queryBuilder.addAggregation(AggregationBuilders.terms("group_by_color").field("color"));
	//执⾏查询,把查询结果直接转为聚合page
	AggregatedPage<Car> aggPage = (AggregatedPage<Car>) carDao.search(queryBuilder.build());
	//从所有的聚合中获取对应名称的聚合
	StringTerms agg = (StringTerms) aggPage.getAggregation("group_by_color");
	//从聚合的结果中获取所有的桶信息,一个桶就是一个分组
	List<StringTerms.Bucket> buckets = agg.getBuckets();
	for (StringTerms.Bucket bucket : buckets) {
		String brand = bucket.getKeyAsString();//颜色
		long docCount = bucket.getDocCount();//该颜色对应的数量
		System.out.println("color = " + brand+" 总数:"+docCount);
	}
}

(5)代码示例2,

@Test
public void testQuerySelfSubAggs(){
	//查询条件的构建器
	NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder().withQuery(QueryBuilders.matchAllQuery());
	//排除所有的字段查询,
	queryBuilder.withSourceFilter(new FetchSourceFilter(new String[]{},null));
	//添加聚合条件,按颜色分组,并对每一组求平均价格
	queryBuilder.addAggregation(AggregationBuilders.terms("group_by_color").field("color")
				.subAggregation(AggregationBuilders.avg("avg_price").field("price")));
	//执⾏查询,把查询结果直接转为聚合page
	AggregatedPage<Car> aggPage = (AggregatedPage<Car>) carDao.search(queryBuilder.build());
	//从所有的聚合中获取对应名称的聚合
	StringTerms agg = (StringTerms) aggPage.getAggregation("group_by_color");
	//从聚合的结果中获取所有的桶信息
	List<StringTerms.Bucket> buckets = agg.getBuckets();
	for (StringTerms.Bucket bucket : buckets) {
		String brand = bucket.getKeyAsString();
		long docCount = bucket.getDocCount();
		//取得内部聚合
		InternalAvg avg = (InternalAvg) bucket.getAggregations().asMap().get("avg_price");
		System.out.println("brand = " + brand+" 总数:"+docCount+" 平均价格:"+avg.getValue());
	}
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

ElasticSearch入门 的相关文章

  • 获取文件的锁

    我想在对特定文件开始 threo read 时获取文件上的锁定 以便其他应用程序无法读取已锁定的文件并希望在线程终止时释放锁定文件 您可以获得一个FileLock https docs oracle com javase 8 docs ap
  • Java 7 默认语言环境

    我刚刚安装了 jre7 我很惊讶地发现我的默认区域设置现在是 en US 对于jre6 它是de CH 与jre7有什么不同 默认区域设置不再是操作系统之一吗 顺便说一句 我使用的是Windows7 谢谢你的回答 编辑 我已经看到了语言环境
  • Android 中的列表(特别是 RecyclerView 和 CardView)如何工作

    请原谅我问这个问题 但我是 Android 开发新手 尽管我正在尝试了解developer android com 网站上的基础知识 但大多数示例 即使他们说它们是为 Android Studio 构建的 尚未设置为使用 Gradle 因此
  • 当路径的点超出视野时,Android Canvas 不会绘制路径

    我在绘制路径时遇到了 Android Canvas 的一些问题 我的情况是 我有一个相对布局工作 如地图视图 不使用 google api 或类似的东西 我必须在该视图上绘制一条路径 canvas drawPath polyPath bor
  • HAProxy SSL终止+客户端证书验证+curl/java客户端

    我希望使用我自己的自签名证书在 HAProxy 上进行 SSL 终止 并使用我创建的客户端证书验证客户端访问 我通过以下方式创建服务器 也是 CA 证书 openssl genrsa out ca key 1024 openssl req
  • 如何将jscrollpane添加到jframe?

    我有以下源代码 有人可以给我建议如何将 jscrollpane 添加到 jframe 上吗 我尝试了几次将其添加到 jframe 但没有任何进展 它甚至没有显示 public class Form3 JFrame jframe new JF
  • 您建议使用哪种压缩(GZIP 是最流行的)servlet 过滤器?

    我正在寻找一个用于大容量网络应用程序的 GZIP servlet 过滤器 我不想使用容器特定的选项 要求 能够压缩响应负载 XML Faster 已在大批量应用的生产中得到验证 应适当设置适当内容编码 跨容器移植 可选择解压缩请求 谢谢 我
  • 如何在java Spring Boot中实现通用服务类?

    我有许多具有重复代码的服务 我想知道如何实现通用服务 以便我的所有服务都可以扩展它 服务接口示例 重复代码 Service public interface IUserService List
  • 在 MongoDB 和 Apache Solr 之间同步数据的简单方法

    我最近开始使用 MongoDB 和 Apache Solr 我使用 MongoDB 作为数据存储 并且希望 Apache Solr 为我的数据创建索引 以实现应用程序中的搜索功能 经过一些研究 我发现 基本上有两种方法可以在 MongoDB
  • 是否可以从 servlet 内部以编程方式设置请求上下文路径?

    这是一个特殊情况 我陷入了处理 企业 网络应用程序的困境 企业应用程序正在调用request getContext 并将其与另一个字符串进行比较 我发现我可以使用 getServletContext getContextPath 获取 se
  • 从休眠乐观锁定异常中恢复

    我有一个这样的方法 Transactional propagation Propagation REQUIRES NEW public void doSomeWork Entity entity dao loadEntity do some
  • 用于缓存的 Servlet 过滤器

    我正在创建一个用于缓存的 servlet 过滤器 这个想法是将响应主体缓存到memcached 响应正文由以下方式生成 结果是一个字符串 response getWriter print result 我的问题是 由于响应正文将不加修改地放
  • Java:如何确定文件所在的驱动器类型?

    Java 是否有一种独立于平台的方法来检测文件所在的驱动器类型 基本上我有兴趣区分 硬盘 可移动驱动器 如 USB 记忆棒 和网络共享 JNI JNA 解决方案不会有帮助 可以假设 Java 7 您可以使用 Java 执行 cmd fsut
  • Play.application() 的替代方案是什么

    我是 Play 框架的新手 我想读取conf文件夹中的一个文件 所以我用了Play application classloader getResources Data json nextElement getFile 但我知道 play P
  • 如何从 Ant 启动聚合 jetty-server JAR?

    背景 免责声明 I have veryJava 经验很少 我们之前在 Ant 构建期间使用了 Jetty 6 的包装版本来处理按需静态内容 JS CSS 图像 HTML 因此我们可以使用 PhantomJS 针对 HTTP 托管环境运行单元
  • 替换文件中的字符串

    我正在寻找一种方法来替换文件中的字符串而不将整个文件读入内存 通常我会使用 Reader 和 Writer 即如下所示 public static void replace String oldstring String newstring
  • 使用 JFreeChart 为两个系列设置不同的 y 轴

    我正在使用 JFreeChart 使用折线图绘制两个数据系列 XYSeries 复杂的因素是 其中一个数据系列的 y 值通常远高于第二个数据系列的 y 值 假设第一个系列的 y 值约为数百万数量级 而第二个数据系列的 y 值约为数百万数量级
  • 将对象从手机共享到 Android Wear

    我创建了一个应用程序 在此应用程序中 您拥有包含 2 个字符串 姓名和年龄 和一个位图 头像 的对象 所有内容都保存到 sqlite 数据库中 现在我希望可以在我的智能手表上访问这些对象 所以我想实现的是你可以去启动 启动应用程序并向左和向
  • 如何使用通配符模拟泛型方法的行为

    我正在使用 EasyMock 3 2 我想基于 Spring Security 为我的部分安全系统编写一个测试 我想嘲笑Authentication http docs spring io autorepo docs spring secu
  • 基于 Spring Boot 的测试中的上下文层次结构

    我的 Spring Boot 应用程序是这样启动的 new SpringApplicationBuilder sources ParentCtxConfig class child ChildFirstCtxConfig class sib

随机推荐

  • 7种有效安全的网页抓取方法,如何避免被禁止?

    网页抓取是一种从互联网上抓取网页内容的过程 但在网络抓取种相信您也经常遇到障碍 尤其是做跨境业务的 在抓取国外的网站时更有难度 但我们站在您的立场上 提供七种有效的方法来进行网页抓取而不被阻止 最大限度地降低网站禁令的风险 并帮助您应对相关
  • linux 快速安装最新稳定版nginx(CentOS8.1 64位)

    目录 CentOS8 1 安装完成已具备 yum 指令操作 低版本缺少yum 指令自行安装 启动nginx遇到错误 nginx emerg bind to 0 0 0 0 7070 failed 13 Permission denied 配
  • 不用看网课就能学到python的文章(第五天)

    目录 类 对象 实例 类中的成员 面向对象 变量 不用看网课就能学到python的文章 第二天 Why does it work的博客 CSDN博客 不用看网课就能学到python的文章 第三天 Why does it work的博客 CS
  • 自己编写DLL文件——注册——VB工程引用——标准EXE调用(含例子)

    VB6 0的 工程 引用 中有很多控件供用户使用 但有时需要自己编写dll文件以实现某些功能 本文介绍如何自己编写一个简单的dll文件 然后在win7 64位下使用regsvr32注册 并在VB6 0中引用 最后在标准EXE中调用实现某些功
  • ES 版本,及重要特性

    参考 https www cnblogs com flyrock ES release 地址 https www elastic co cn downloads past releases elasticsearch ES版本 发布日期 版
  • 熊啸锋:精准营销及推广的四个步骤,倍增你的利润

    哈喽 我是熊啸锋老师 今天分享的主题是精准营销及推广的四个步骤 作为营销人 企业老板 项目负责人 市场开发人员等 你会经常面临 如何开发客户 如何获得大量的潜在客户名单 等很多的问题 还经常有人抱怨说 我们获取的潜在客户名单不精准 成交率非
  • Linux中清空文件的方法

    Linux中清空文件的方法 平时工作过程中 经常会遇到需要清空linux中某个日志文件的方法 下面总结一下几个常用的方法 以下待清空的文件名统一使用 test txt 表示 方法1 vi 中使用 d 1 输入 vi test txt 回车
  • word添加gif

    word添加gif动图最简单的方法 无需链接无需插件 X to Y的博客 CSDN博客 word插入动图 原文链接 https blog csdn net X To Y article details 124415532 文章目录 word
  • c++ Graphics 实现俄罗斯方块

    俄罗斯方块 一 游戏规则 1 方块种类 2 操作规则 玩家可以通过 按键 功能 a 向左一格 d 向右一格 s 顺时针旋转90度 w 逆时针旋转90度 3 积分规则 玩家根据消除的行列数量获取得分 数量 得分 1行 10分 2行 30分 3
  • Vue中的import中@的作用

    这是webpack的路径别名 相关代码定义在配置文件webpack base config里 resolve 自动补全的扩展名 extensions js vue json 默认路径代理 例如 import Vue from vue 会自动
  • UVA-10603 倒水问题 题解答案代码 算法竞赛入门经典第二版

    GitHub jzplp aoapc UVA Answer 算法竞赛入门经典 例题和习题答案 刘汝佳 第二版 使用广度优先搜索和优先队列 如果找到最小的点则退出 找不到就遍历所有的情况 include
  • 在vue中引入高德地图

    既然要用到高德地图首先要申请成为高德地图开发者 并申请使用高德地图的key这两点在这篇文章就不过多赘述 有需要的小伙伴可以查查资料 或者去高德地图api官网都有很详细的介绍 高德地图官网 简单提一下申请秘钥流程 web端 控制台 gt 应用
  • Android中的关于MDM中的几个方法举例

    首先介绍一下MDM是什么的缩写 MDM是什么 MDM 是 Mobile Device Management 的缩写 中文翻译过来就是移动设备管理 随着移动设备计算能力地增强 移动设备携带越来越方便 移动化办公已经成为一种潮流 一种趋势 企业
  • MATLAB_第二篇神经网络学习_BP神经网络

    非常感谢博主wishes61的分享 这篇博客只是为了记录下第一个神经网络的训练 BP神经网络代码实现 1 BP神经网络的简介和结构参数 1 1 BP神经网络的结构组成 1 2 神经元结构示意图 1 3 BP神经网络训练界面的参数解读 2 B
  • 【华为OD机试】战场索敌(C++ Python Java)2023 B卷

    时间限制 C C 1秒 其他语言 2秒 空间限制 C C 262144K 其他语言524288K 64bit IO Format lld 题目描述 有一个大小是N M的战场地图 被墙壁 分隔成大小不同的区域 上下左右四个方向相邻的空地 属于
  • 蓝牙协议规范--L2CAP

    L2CAP 分析 记住一点 软件和硬件分开理解 数据经由物理通道交互 上层通道由各层协议打通 L2CAP 全称为逻辑链路控制与适配协议 Logical Link Control and Adaptation Protocol 位于基带层之上
  • 聚簇索引与非聚簇索引(也叫二级索引)

    索引 索引 是 存储引擎 用于快速找到记录的一种 数据结构 MYSQL中索引在存储引擎层实现 而非服务器层 索引类型 聚簇索引 非聚簇索引 二级索引 主键索引 辅助索引 复合索引 前缀索引 唯一索引 压缩索引 全文索引 Hash索引 列索引
  • Redis学习笔记2:了解 Redis 入门

    1 Redis是什么 Remote Dictionary Server 远程字典服务 Redis是现在最受欢迎的NoSQL数据库之一 Redis是一个使用ANSI C编写的开源 包含多种数据结构 支持网络 基于内存 可选持久性的键值对存储数
  • 如何的pycharm远程连接服务器Ftp

    话不多说 我们直接开始上图操作 以上就是整体的配置过程
  • ElasticSearch入门

    文章目录 一 ElasticSearch简介 1 什么是ElasticSearch 2 ElasticSearch使用案例 3 ElasticSearch对 Solr 二 ElasticSearch相关概念 术语 1 概述 2 索引 ind