Java API
如果你正在使用 Java,在代码中你可以使用 Elasticsearch 内置的两个客户端:
节点客户端(Node client)
节点客户端作为一个非数据节点加入到本地集群中。换句话说,它本身不保存任何数据,但是它知道数据在集群中的哪个节点中,并且可以把请求转发到正确的节点。
传输客户端(Transport client)
轻量级的传输客户端可以将请求发送到远程集群。它本身不加入集群,但是它可以将请求转发到集群中的一个节点上。
Java 客户端作为节点必须和 Elasticsearch 有相同的 主要 版本;否则,它们之间将无法互相理解。
所有其他语言可以使用 RESTful API 通过端口 9200 和 Elasticsearch 进行通信,你可以用你最喜爱的 web 客户端访问 Elasticsearch 。事实上,正如你所看到的,你甚至可以使用 curl
命令来和 Elasticsearch 交互。
一个 Elasticsearch 请求和任何 HTTP 请求一样由若干相同的部件组成:
curl -X<VERB> '<PROTOCOL>://<HOST>:<PORT>/<PATH>?<QUERY_STRING>' -d '<BODY>'
被< >
标记的部件:
名称 | 解释 |
---|---|
VERB | 适当的 HTTP 方法 或 谓词 : GET、 POST、 PUT、 HEAD 或者 DELETE 。 |
PROTOCOL | http 或者 https(如果你在 Elasticsearch 前面有一个 https 代理) |
HOST | Elasticsearch 集群中任意节点的主机名,或者用 localhost 代表本地机器上的节点。 |
PORT | 运行 Elasticsearch HTTP 服务的端口号,默认是 9200 。 |
PATH | API 的终端路径(例如 _count 将返回集群中文档数量)。Path 可能包含多个组件,例如:_cluster/stats 和 _nodes/stats/jvm 。 |
QUERY_STRING | 任意可选的查询字符串参数 (例如 ?pretty 将格式化地输出 JSON 返回值,使其更容易阅读) |
BODY | 一个 JSON 格式的请求体 (如果请求需要的话) |
以上都是官方文档说的,我也不是很明白,但是我知道的是,可以通过http或者https交互
所以上节安装了kibana,就直接用kibana
交互!
有些看客可能就要说了“你怎么能这么水呢!?自己都没看懂就贴出来”
,根本没有!因为我也是第一次学嘛!
按照官方文档的说法,
xshell
运行几个试试
[root@cs3 /]# curl -XGET 'localhost:9200/_count?pretty' -d '
> {
> "query": {
> "match_all": {}
> }
> }'
{
"count" : 4,
"_shards" : {
"total" : 6,
"successful" : 6,
"skipped" : 0,
"failed" : 0
}
}
[root@cs3 /]#
kibana
运行试试
GET /_count
{
"query": {
"match_all": {}
}
}
输出:
{
"count": 4,
"_shards": {
"total": 6,
"successful": 6,
"skipped": 0,
"failed": 0
}
}
elasticsearch在这里引入了一个
面向文档
的概念
面向文档
在应用程序中对象很少只是一个简单的键和值的列表。通常,它们拥有更复杂的数据结构,可能包括日期、地理信息、其他对象或者数组等。
也许有一天你想把这些对象存储在数据库中。使用关系型数据库的行和列存储,这相当于是把一个表现力丰富的对象塞到一个非常大的电子表格中:为了适应表结构,你必须设法将这个对象扁平化--通常一个字段对应一列--而且每次查询时又需要将其重新构造为对象。
Elasticsearch 是 面向文档 的,意味着它存储整个对象或 文档_。Elasticsearch 不仅存储文档,而且 _索引 每个文档的内容,使之可以被检索。在 Elasticsearch 中,我们对文档进行索引、检索、排序和过滤--而不是对行列数据。这是一种完全不同的思考数据的方式,也是 Elasticsearch 能支持复杂全文检索的原因。
Elasticsearch 使用 JavaScript Object Notation(或者 JSON)作为文档的序列化格式。
下面这个 JSON 文档代表了一个 user 对象:
{
"email": "john@smith.com",
"first_name": "John",
"last_name": "Smith",
"info": {
"bio": "Eco-warrior and defender of the weak",
"age": 25,
"interests": [ "dolphins", "whales" ]
},
"join_date": "2014/05/01"
}
实操
创建一个雇员目录
索引:存储数据到 Elasticsearch 的行为叫做 索引 ,但在索引一个文档之前,需要确定将文档存储在哪里。
一个 Elasticsearch 集群可以包含多个 索引 ,相应的每个索引可以包含多个 类型 。这些不同的类型存储着多个 文档 ,每个文档又有 多个 属性 。
索引 这个词在 Elasticsearch 语境中有多种含义, 这里有必要做一些说明:
索引(名词)
:
如前所述,一个 索引 类似于传统关系数据库中的一个 数据库 ,是一个存储关系型文档的地方。索引
(index) 的复数词为indices
或indexes
。
索引(动词):
索引一个文档
就是存储一个文档到一个索引
(名词)中以便被检索和查询。这非常类似于 SQL 语句中的INSERT
关键词,除了文档已存在时,新文档会替换旧文档情况之外。
倒排索引
:
关系型数据库通过增加一个 索引 比如一个 B树(B-tree)索引 到指定的列上,以便提升数据检索速度。Elasticsearch 和 Lucene 使用了一个叫做倒排索引
的结构来达到相同的目的。
默认的,一个文档中的每一个属性都是被索引
的(有一个倒排索引)和可搜索的。一个没有倒排索引的属性是不能被搜索到的。我们将在 倒排索引 讨论倒排索引的更多细节。
插入:
PUT /megacorp/employee/1
{
"first_name" : "John",
"last_name" : "Smith",
"age" : 25,
"about" : "I love to go rock climbing",
"interests": [ "sports", "music" ]
}
注意,路径 /megacorp/employee/1 包含了三部分的信息:
- | - |
---|---|
megacorp | 索引名称 |
employee | 类型名称 |
1 | 特定雇员的ID |
请求体 —— JSON 文档 —— 包含了这位员工的所有详细信息,他的名字叫 John Smith ,今年 25 岁,喜欢攀岩。
查询
GET /megacorp/employee/1
删除
DELETE /megacorp/employee/1
更新
更新和插入一样,使用PUT
PUT /megacorp/employee/1
{
"first_name" : "John",
"last_name" : "Smith",
"age" : 25,
"about" : "我喜欢打游戏",
"interests": [ "sports", "music" ]
}
使用
HEAD
指令来检查文档是否存在
HEAD /megacorp/employee/1
轻量级搜索
搜索所有
GET /megacorp/employee/_search
当然直接搜索megacorp目录下的所有数据也是可以的
GET /tang/_search
image.png
搜索姓氏为 Smith
的雇员
GET /megacorp/employee/_search?q=last_name:Smith
使用_search
端点,并将查询本身赋值给参数 q=
。返回结果给出了所有的 Smith:
使用查询表达式搜索
Elasticsearch 提供一个丰富灵活的查询语言叫做 查询表达式 , 它支持构建更加复杂和健壮的查询。
领域特定语言 (DSL), 使用 JSON 构造了一个请求。我们可以像这样重写之前的查询所有名为 Smith 的搜索 :
GET /megacorp/employee/_search
{
"query" : {
"match" : {
"last_name" : "Smith"
}
}
}
match
:不再使用 query-string 参数,而是一个请求体替代。这个请求使用 JSON 构造,并使用了一个 match 查询
更复杂的搜索
使用过滤器,搜索姓氏为 Smith 的员工,且年龄大于 30
GET /megacorp/employee/_search
{
"query" : {
"bool": {
"must": {
"match" : {
"last_name" : "smith"
}
},
"filter": {
"range" : {
"age" : { "gt" : 30 }
}
}
}
}
}
全文搜索
GET /megacorp/employee/_search
{
"query" : {
"match" : {
"about" : "rock climbing"
}
}
}
这里涉及到一个概念叫:相关性搜索
Elasticsearch默认按照相关性得分排序,即每个文档跟查询的匹配程度。第一个最高得分的结果很明显:John Smith 的
about
属性清楚地写着 “rock climbing” 。
但为什么 Jane Smith 也作为结果返回了呢?原因是她的about
属性里提到了 “rock” 。因为只有 “rock” 而没有 “climbing” ,所以她的相关性得分低于 John 的。
这是一个很好的案例,阐明了 Elasticsearch 如何 在 全文属性上搜索并返回相关性最强的结果。Elasticsearch中的 相关性 概念非常重要,也是完全区别于传统关系型数据库的一个概念,数据库中的一条记录要么匹配要么不匹配。
短语搜索
精确匹配一系列单词或者短语
仅匹配同时包含 “rock” 和 “climbing” ,并且 二者以短语 “rock climbing” 的形式紧挨着的雇员记录。
GET /megacorp/employee/_search
{
"query" : {
"match_phrase" : {
"about" : "rock climbing"
}
}
}
高亮搜索
GET /megacorp/employee/_search
{
"query" : {
"match_phrase" : {
"about" : "打游戏"
}
},
"highlight": {
"fields" : {
"about" : {}
}
}
}
当执行该查询时,返回结果与之前一样,与此同时结果中还多了一个叫做 highlight 的部分。这个部分包含了 about 属性匹配的文本片段,并以 HTML 标签
<em></em>
封装:
分析
Elasticsearch 有一个功能叫聚合(aggregations),允许我们基于数据生成一些精细的分析结果。聚合与 SQL 中的 GROUP BY
类似但更强大。
GET /megacorp/employee/_search
{
"aggs": {
"all_interests": {
"terms": { "field": "interests" }
}
}
}
然后你就会发现报错了
Fielddata is disabled on text fields by default. Set fielddata=true on [interests] in order to load
这是因为5.x后对排序,聚合这些操作用单独的数据结构(fielddata)缓存到内存里了,需要单独开启,官方解释在此fielddata
先执行这一步
PUT megacorp/_mapping/employee/
{
"properties": {
"interests": {
"type": "text",
"fielddata": true
}
}
}
如果想知道叫 Smith 的员工中最受欢迎的兴趣爱好,可以直接构造一个组合查询:
GET /megacorp/employee/_search
{
"query": {
"match": {
"last_name": "smith"
}
},
"aggs": {
"all_interests": {
"terms": {
"field": "interests"
}
}
}
}
这些语法也不用深究,之后会详细说明,这些用来体会elasticsearch的交互。
网友评论