elasticsearch学习笔记(一)

elasticsearch初识:
当然 Elasticsearch 并不仅仅是 Lucene 那么简单,它不仅包括了全文搜索功能,还可以进行以下工作:
分布式实时文件存储,并将每一个字段都编入索引,使其可以被搜索。
实时分析的分布式搜索引擎。
可以扩展到上百台服务器,处理PB级别的结构化或非结构化数据。
这么多的功能被集成到一台服务器上,你可以轻松地通过客户端或者任何你喜欢的程序语言与 ES 的 RESTful API 进行交流。

集群和节点

节点 是 Elasticsearch 运行的实例。集群 是一组有着同样cluster.name的节点,在同一网段的,不需要特殊的配置,Elasticsearch 会自动发现同网段的节点,它们协同工作,互相分享数据,提供了故障转移和扩展的功能。当然一个节点也可以是一个集群。

与 Elasticsearch 通信

如果你使用的是 JAVA,Elasticsearch 内置了两个客户端,你可以在你的代码中使用:
节点客户端: 节点客户端以一个 无数据节点 的身份加入了一个集群。换句话说,它自身是没有任何数据的,但是他知道什么数据在集群中的哪一个节点上,然后就可以请求转发到正确的节点上并进行连接。
传输客户端: 更加轻量的传输客户端可以被用来向远程集群发送请求。他并不加入集群本身,而是把请求转发到集群中的节点。

这两个客户端都使用 Elasticsearch 的 传输 协议,通过9300端口与 java 客户端进行通信。集群中的各个节点也是通过9300端口进行通信。如果这个端口被禁止了,那么你的节点们将不能组成一个集群。
ps:
Java 的客户端的版本号必须要与 Elasticsearch 节点所用的版本号一样,不然他们之间可能无法识别。
关系数据库 ⇒ 数据库 ⇒ 表 ⇒ 行 ⇒ 列(Columns)
Elasticsearch ⇒ 索引 ⇒ 类型 ⇒ 文档 ⇒ 字段(Fields)

一个 Elasticsearch 集群可以包含多个 索引(数据库),也就是说其中包含了很多 类型(表)。这些类型中包含了很多的 文档(行),然后每个文档中又包含了很多的 字段(列)。
索引 索引 索引

你可能发现在 Elasticsearch 中,索引这个词汇已经被赋予了太多意义,所以在这里我们有必要澄清一下:
索引 (名词)
如上文所说,一个 索引 就类似于传统关系型数据库中的 数据库。这里就是存储相关文档的的地方。
索引 (动词)
为一个文档创建索引 是把一个文档存储到一个索引(名词)中的过程,这样它才能被检索。这个过程非常类似于 SQL 中的 INSERT 命令,如果已经存在文档,新的文档将会覆盖旧的文档。
反向索引
在关系数据库中的某列添加一个 索引,比如多路搜索树(B-Tree)索引,就可以加速数据的取回速度, Elasticsearch 以及 Lucene 使用的是一个叫做 反向索引(inverted index) 的结构来实现相同的功能。

Elasticsearch :
简易搜索

GET 命令真的相当简单,你只需要告诉它你要什么即可。接下来,我们来试一下稍微复杂一点的搜索。
我们首先要完成一个最简单的搜索命令来搜索全部员工:
GET /t_ld_gnlk_ts/property/_search
你可以发现我们正在使用 megacorp 索引,employee 类型,但是我们我们并没有指定文档的ID,我们现在使用的是 _search 端口。你可以再返回的 hits 中发现我们录入的三个文档。搜索会默认返回最前的10个数值。

curl 192.168.0.23:9200/t_ld_gnlk_ts/property/_search?pretty = true -d ’ {“query”:{“term”{“ZHENGJIANHM”:”ouaeooofbmoooboiii”}}}’
curl 192.168.0.23:9200/t_ld_gnlk_ts/property/_search?pretty = true q=”ZHENGJIANHM”:”ouaeooofbmoooboiii”
pretty = true:表示返回标准json
_search:表示查询
如果是查询全部数据:curl 192.168.0.23:9200/t_ld_gnlk_ts/property/_search
Elasticsearch 查询的时候,字段名严重区分大小写。

使用Query DSL搜索

查询字符串是通过命令语句完成 点对点(ad hoc) 的搜索,但是这也有它的局限性(可参阅《搜索局限性》章节)。Elasticsearch 提供了更加丰富灵活的查询语言,它被称作 Query DSL,通过它你可以完成更加复杂、强大的搜索任务。
DSL (Domain Specific Language 领域特定语言) 需要使用 JSON 作为主体,我们还可以这样查询姓 Smith 的员工:

GET /megacorp/employee/_search
{
“query” : {
“match” : {
“last_name” : “Smith”
}
}
}
更加复杂的搜索

接下来,我们再提高一点儿搜索的难度。我们依旧要寻找出姓 Smith 的员工,但是我们还将添加一个年龄大于30岁的限定条件。我们的查询语句将会有一些细微的调整来以识别结构化搜索的限定条件 filter(过滤器):
GET /megacorp/employee/_search
{
“query” : {
“filtered” : {
“filter” : {
“range” : {
“age” : { “gt” : 30 } <1>
}
},
“query” : {
“match” : {
“last_name” : “Smith” <2>
}
}
}
}
}

全文搜索

上面的搜索都很简单:名字搜索、通过年龄过滤。接下来我们来学习一下更加复杂的搜索,全文搜索——一项在传统数据库很难实现的功能。 我们将会搜索所有喜欢 rock climbing 的员工:
GET /megacorp/employee/_search
{
“query” : {
“match” : {
“about” : “rock climbing”
}
}
}

段落搜索

能够找出每个字段中的独立单词固然很好,但是有的时候你可能还需要去匹配精确的短语或者 段落。例如,我们只需要查询到 about 字段只包含 rock climbing 的短语的员工。
为了实现这个效果,我们将对 match 查询变为 match_phrase 查询:
GET /megacorp/employee/_search
{
“query” : {
“match_phrase” : {
“about” : “rock climbing”
}
}
}
分布式特性

Elasticsearch 很努力地在避免复杂的分布式系统,很多操作都是自动完成的:
可以将你的文档分区到不同容器或者 分片 中,这些文档可能被存在一个节点或者多个节点。
跨节点平衡集群中节点间的索引与搜索负载。
自动复制你的数据以提供冗余副本,防止硬件错误导致数据丢失。
自动在节点之间路由,以帮助你找到你想要的数据。
无缝扩展或者恢复你的集群。

在 elasticsearch 中,分片用来分配集群中的数据。把分片想象成一个数据的容器。数据被存储在分片中,然后分片又被分配在集群的节点上。当你的集群扩展或者缩小时,elasticsearch 会自动的在节点之间迁移分配分片,以便集群保持均衡。
分片分为 主分片(primary shard) 以及 从分片(replica shard) 两种。在你的索引中,每一个文档都属于一个主分片,所以具体有多少主分片取决于你的索引能存储多少数据。

集群的健康状况 yellow 意味着所有的 主分片(primary shards) 启动并且运行了,这时集群已经可以成功的处理任意请求,但是 从分片(replica shards) 没有完全被激活。事实上,当前这三个从分片都处于 unassigned(未分配)的状态,它们还未被分配到节点上。在同一个节点上保存相同的数据副本是没有必要的,如果这个节点故障了,就等同于所有的数据副本也丢失了。

_index

索引 类似于传统数据库中的”数据库”——也就是我们存储并且索引相关数据的地方。
TIP:

在Elasticsearch中,我们的数据都在分片中被存储以及索引,索引只是一个逻辑命名空间,它可以将一个或多个分片组合在一起。然而,这只是一个内部的运作原理——我们的程序可以根本不用关心分片。对于我们的程序来说,我们的文档存储在索引中。剩下的交给Elasticsearch就可以了。
我们只需要选择一个索引的名字。这个名称必须要全部小写,也不能以下划线开头,不能包含逗号。我们可以用website作为我们索引的名字。

_id

id是一个字符串,当它与_index以及_type组合时,就可以来代表Elasticsearch中一个特定的文档。我们创建了一个新的文档时,你可以自己提供一个_id,或者也可以让Elasticsearch帮你生成一个。

这个返回值意味着我们的索引请求已经被成功创建,其中还包含了_index, _type以及_id的元数据,以及一个新的元素_version。
在Elasticsearch中,每一个文档都有一个版本号码。每当文档产生变化时(包括删除),_version就会增大。在《版本控制》中,我们将会详细讲解如何使用_version的数字来确认你的程序不会随意替换掉不想覆盖的数据。

检索文档中的一部分

通常,GET请求会将整个文档放入_source字段中一并返回。但是可能你只需要title字段。你可以使用_source得到指定字段。如果需要多个字段你可以使用逗号分隔:
GET /website/blog/123?_source=title,text
现在_source字段中就只会显示你指定的字段:
{
“_index” : “website”,
“_type” : “blog”,
“_id” : “123”,
“_version” : 1,
“exists” : true,
“_source” : {
“title”: “My first blog entry” ,
“text”: “Just trying this out…”
}
}
或者你只想得到_source字段而不要其他的元数据,你可以这样请求:
GET /website/blog/123/_source
这样结果就只返回:
{
“title”: “My first blog entry”,
“text”: “Just trying this out…”,
“date”: “2014/01/01”
}

更新整个文档

在Documents中的文档是不可改变的。所以如果我们需要改变已经存在的文档,我们可以使用《索引》中提到的indexAPI来重新索引或者替换掉它:
PUT /website/blog/123
{
“title”: “My first blog entry”,
“text”: “I am starting to get the hang of this…”,
“date”: “2014/01/02”
}
在反馈中,我们可以发现Elasticsearch已经将_version数值增加了:
{
“_index” : “website”,
“_type” : “blog”,
“_id” : “123”,
“_version” : 2,
“created”: false <1>
}
created被标记为 false是因为在同索引、同类型下已经存在同ID的文档。
在内部,Elasticsearch已经将旧文档标记为删除并且添加了新的文档。旧的文档并不会立即消失,但是你也无法访问他。Elasticsearch会在你继续添加更多数据的时候在后台清理已经删除的文件。
在本章的后面,我们将会在《局部更新》中介绍最新更新的API。这个API允许你修改局部,但是原理和下方的完全一样:
从旧的文档中检索JSON
修改它
删除修的文档
索引一个新的文档
唯一不同的是,使用了updateAPI你就不需要使用get然后再操作index请求了。

创建一个文档

当我们索引一个文档时,如何确定我们是创建了一个新的文档还是覆盖了一个已经存在的文档呢?
请牢记_index,_type以及_id组成了唯一的文档标记,所以为了确定我们创建的是全新的内容,最简单的方法就是使用POST方法,让Elasticsearch自动创建不同的_id:
POST /website/blog/
{ … }

然而,我们可能已经决定好了_id,所以需要告诉Elasticsearch只有当_index,_type以及_id这3个属性全部相同的文档不存在时才接受我们的请求。实现这个目的有两种方法,他们实质上是一样的,你可以选择你认为方便的那种:
第一种是在查询中添加op_type参数:
PUT /website/blog/123?op_type=create
{ … }
或者在请求最后添加 /_create:
PUT /website/blog/123/_create
{ … }
如果成功创建了新的文档,Elasticsearch将会返回常见的元数据以及201 Created的HTTP反馈码。
而如果存在同名文件,Elasticsearch将会返回一个409 Conflict的HTTP反馈码,以及如下方的错误信息:
{
“error” : “DocumentAlreadyExistsException[[website][4] [blog][123]:
document already exists]”,
“status” : 409
}

删除一个文档

删除文档的基本模式和之前的基本一样,只不过是需要更换成DELETE方法:
DELETE /website/blog/123
如果文档存在,那么Elasticsearch就会返回一个200 OK的HTTP响应码,返回的结果就会像下面展示的一样。请注意_version的数字已经增加了。
{
“found” : true,
“_index” : “website”,
“_type” : “blog”,
“_id” : “123”,
“_version” : 3
}
如果文档不存在,那么我们就会得到一个404 Not Found的响应码,返回的内容就会是这样的:
{
“found” : false,
“_index” : “website”,
“_type” : “blog”,
“_id” : “123”,
“_version” : 4
}
尽管文档并不存在(”found”值为false),但是_version的数值仍然增加了。这个就是内部管理的一部分,它保证了我们在多个节点间的不同操作的顺序都被正确标记了。

处理冲突

当你使用索引API来更新一个文档时,我们先看到了原始文档,然后修改它,最后一次性地将整个新文档进行再次索引处理。Elasticsearch会根据请求发出的顺序来选择出最新的一个文档进行保存。但是,如果在你修改文档的同时其他人也发出了指令,那么他们的修改将会丢失。
很长时间以来,这其实都不是什么大问题。或许我们的主要数据还是存储在一个关系数据库中,而我们只是将为了可以搜索,才将这些数据拷贝到Elasticsearch中。或许发生多个人同时修改一个文件的概率很小,又或者这些偶然的数据丢失并不会影响到我们的正常使用。
但是有些时候如果我们丢失了数据就会出大问题。想象一下,如果我们使用Elasticsearch来存储一个网店的商品数量。每当我们卖出一件,我们就会将这个数量减少一个。
突然有一天,老板决定来个大促销。瞬间,每秒就产生了多笔交易。并行处理,多个进程来处理交易

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值