ElasticSearch是一个高度可扩展的开源搜索引擎并使用REST API,因此您值得拥有。 在本教程中,将介绍开始使用ElasticSearch的一些主要概念。html
ElasticSearch能够从elasticsearch.org下载对应的文件格式,如ZIP
和TAR.GZ
。下载并提取一个运行它的软件包以后不会容易得多,须要提早安装Java运行时环境。java
在本文章中,所使用的环境是Windows,因此这里只介绍在Windows上运行ElasticSearch,可从命令窗口运行位于bin
文件夹中的elasticsearch.bat
。这将会启动ElasticSearch在控制台的前台运行,这意味着咱们可在控制台中看到运行信息或一些错误信息,并可使用CTRL + C中止或关闭它。node
当前版本是: elasticsearch-5.2.0
下载连接: http://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-5.2.0.zipweb
把下载好的文件 elasticsearch-5.2.0.zip
解压到 D:\software\elasticsearch-5.2.0
,其目录结构以下所示 -chrome
启动 ElasticSearch -shell
Microsoft Windows [版本 10.0.10586] (c) 2015 Microsoft Corporation。保留全部权利。
C:\Users\Administrator>d: D:\>cd software\elasticsearch-5.2.0 D:\software\elasticsearch-5.2.0>cd bin D:\software\elasticsearch-5.2.0\bin>elasticsearch.bat [2017-01-28T14:10:32,177][INFO ][o.e.n.Node ] [] initializing ... [2017-01-28T14:10:32,670][INFO ][o.e.e.NodeEnvironment ] [SnafGWM] using [1] data paths, mounts [[Software (D:)]], net usable_space [61.6gb], net total_space [139gb], spins? [unknown], types [NTFS] [2017-01-28T14:10:32,686][INFO ][o.e.e.NodeEnvironment ] [SnafGWM] heap size [1.9gb], compressed ordinary object pointers [true] [2017-01-28T14:10:32,686][INFO ][o.e.n.Node ] node name [SnafGWM] derived from node ID [SnafGWMWRzmfwTKP6VJClA]; set [node.name] to override [2017-01-28T14:10:32,717][INFO ][o.e.n.Node ] version[5.2.0], pid[9724], build[24e05b9/2017-01-24T19:52:35.800Z], OS[Windows 10/10.0/amd64], JVM[Oracle Corporation/Java HotSpot(TM) 64-Bit Server VM/1.8.0_65/25.65-b01] [2017-01-28T14:10:35,271][INFO ][o.e.p.PluginsService ] [SnafGWM] loaded module [aggs-matrix-stats] [2017-01-28T14:10:35,271][INFO ][o.e.p.PluginsService ] [SnafGWM] loaded module [ingest-common] [2017-01-28T14:10:35,271][INFO ][o.e.p.PluginsService ] [SnafGWM] loaded module [lang-expression] [2017-01-28T14:10:35,271][INFO ][o.e.p.PluginsService ] [SnafGWM] loaded module [lang-groovy] [2017-01-28T14:10:35,271][INFO ][o.e.p.PluginsService ] [SnafGWM] loaded module [lang-mustache] [2017-01-28T14:10:35,287][INFO ][o.e.p.PluginsService ] [SnafGWM] loaded module [lang-painless] [2017-01-28T14:10:35,287][INFO ][o.e.p.PluginsService ] [SnafGWM] loaded module [percolator] [2017-01-28T14:10:35,288][INFO ][o.e.p.PluginsService ] [SnafGWM] loaded module [reindex] [2017-01-28T14:10:35,290][INFO ][o.e.p.PluginsService ] [SnafGWM] loaded module [transport-netty3] [2017-01-28T14:10:35,291][INFO ][o.e.p.PluginsService ] [SnafGWM] loaded module [transport-netty4] [2017-01-28T14:10:35,292][INFO ][o.e.p.PluginsService ] [SnafGWM] no plugins loaded [2017-01-28T14:10:41,394][INFO ][o.e.n.Node ] initialized [2017-01-28T14:10:41,397][INFO ][o.e.n.Node ] [SnafGWM] starting ... [2017-01-28T14:10:42,657][INFO ][o.e.t.TransportService ] [SnafGWM] publish_address {127.0.0.1:9300}, bound_addresses {127.0.0.1:9300}, {[::1]:9300} [2017-01-28T14:10:46,439][INFO ][o.e.c.s.ClusterService ] [SnafGWM] new_master {SnafGWM}{SnafGWMWRzmfwTKP6VJClA}{vG5mFSENST6eo-yl_O8HuA}{127.0.0.1}{127.0.0.1:9300}, reason: zen-disco-elected-as-master ([0] nodes joined) [2017-01-28T14:10:48,628][INFO ][o.e.h.HttpServer ] [SnafGWM] publish_address {127.0.0.1:9200}, bound_addresses {127.0.0.1:9200}, {[::1]:9200} [2017-01-28T14:10:48,628][INFO ][o.e.n.Node ] [SnafGWM] started [2017-01-28T14:10:48,928][INFO ][o.e.g.GatewayService ] [SnafGWM] recovered [0] indices into cluster_state
在启动过程当中,ElasticSearch的实例运行会占用大量的内存,因此在这一过程当中,电脑会变得比较慢,须要耐心等待,启动加载完成后电脑就能够正常使用了。数据库
若是您没有安装Java运行时或没有正确配置,应该不会看到像上面的输出,而是一个消息说“JAVA_HOME环境变量必须设置!“ 要解决这个问题,首先下载并安装Java,其次,确保已正确配置
JAVA_HOME
环境变量(或参考 - Java JDK安装和配置)。express
当ElasticSearch的实例并运行,您可使用localhost:9200
,基于JSON的REST API与ElasticSearch进行通讯。使用任何HTTP客户端来通讯。在ElasticSearch本身的文档中,全部示例都使用curl。 可是,当使用API时也可以使用图形客户端(如Fiddler或RESTClient),这样操做起更方便直观一些。json
更方便的是Chrome插件Sense。 Sense提供了一个专门用于使用ElasticSearch的REST API的简单用户界面。 它还具备许多方便的功能,例如:ElasticSearch的查询语法的自动完成功能以及curl格式的复制和粘贴请求,从而能够方便地在文档中运行示例。windows
咱们将在本教程中使用sense来执行curl请求,建议安装Sense并使用它学习后续文章内容。
安装完成后,在Chrome的右上角找到Sense的图标。 第一次单击它运行Sense时,会为您准备一个很是简单的示例请求。以下图所示 -
上述请求将执行最简单的搜索查询,匹配服务器上全部索引中的全部文档。针对ElasticSearch运行,Sense提供的最简单的查询,在响应结果的数据中并无查询到任何数据,由于没有任何索引。以下所示 -
{ "took": 1, "timed_out": false, "_shards": { "total": 0, "successful": 0, "failed": 0 }, "hits": { "total": 0, "max_score": 0, "hits": [] } }
下一步咱们来学习添加一些数据和索引,来修复这个问题。
想要使用ElasticSearch,用于搜索第一步就是使用一些数据填充来索引,CRUD表“建立”或者“索引”。咱们还将学习如何更新,读取和删除文档。
在ElasticSearch索引中,对应于CRUD中的“建立”和“更新” - 若是对具备给定类型的文档进行索引,而且要插入原先不存在的ID。 若是具备相同类型和ID的文档已存在,则会被覆盖。
要索引第一个JSON对象,咱们对REST API建立一个PUT请求到一个由索引名称,类型名称和ID组成的URL。 也就是:http://localhost:9200/<index>/<type>/[<id>]
。
索引和类型是必需的,而id
部分是可选的。若是不指定ID
,ElasticSearch会为咱们生成一个ID
。 可是,若是不指定id,应该使用HTTP的POST
而不是PUT
请求。
索引名称是任意的。若是服务器上没有此名称的索引,则将使用默认配置来建立一个索引。
至于类型名称,它也是任意的。 它有几个用途,包括:
如今咱们来索引一些内容! 能够把任何东西放到索引中,只要它能够表示为单个JSON对象。 在本教程中,使用索引和搜索电影的一个示例。这是一个经典的电影对象信息:
{ "title": "The Godfather", "director": "Francis Ford Coppola", "year": 1972 }
要建立一个索引,这里使用索引的名称为“movies”,类型名称(“movie”)和id(“1”),并按照上述模式使用JSON对象在正文中进行请求。
curl -XPUT "http://localhost:9200/movies/movie/1" -d' { "title": "The Godfather", "director": "Francis Ford Coppola", "year": 1972 }'
可使用curl来执行它,也可使用Sense。这里使用Sense,能够本身填充URL,方法和请求正文,或者您以复制上述curl示例,将光标置于Sense中的正文字段中写入上面的Json对象,而后按点击绿色小箭头来执行建立索引操做。以下图所示 -
执行请求后,能够看到接收到来自ElasticSearch响应的JSON对象。以下所示 -
{ "_index": "movies", "_type": "movie", "_id": "1", "_version": 1, "result": "created", "_shards": { "total": 2, "successful": 1, "failed": 0 }, "created": true }
响应对象包含有关索引操做的信息,例如它是否成功(“ok”)和文档ID,若是不指定则ElasticSearch会本身生成一个。
若是运行Sense提供的默认搜索请求(可使用Sense中的“历史记录”按钮访问,由于确实已执行它)过了,就会看到返回有数据的结果。
{ "took": 146, "timed_out": false, "_shards": { "total": 5, "successful": 5, "failed": 0 }, "hits": { "total": 1, "max_score": 1, "hits": [ { "_index": "movies", "_type": "movie", "_id": "1", "_score": 1, "_source": { "title": "The Godfather", "director": "Francis Ford Coppola", "year": 1972 } } ] } }
在上面返回结果中,看到的是搜索结果而不是错误或是空的结果。
如今,在索引中有了一部电影信息,接下来来了解如何更新它,添加一个类型列表。要作到这一点,只需使用相同的ID索引它。使用与以前彻底相同的索引请求,但类型扩展了JSON对象。
curl -XPUT "http://localhost:9200/movies/movie/1" -d' { "title": "The Godfather", "director": "Francis Ford Coppola", "year": 1972, "genres": ["Crime", "Drama"] }'
ElasticSearch的响应结果与前面的大致上同样,但有一点区别,结果对象中的_version
属性的值为2
,而不是1
。响应结果以下 -
{ "_index": "movies", "_type": "movie", "_id": "1", "_version": 2, "result": "updated", "_shards": { "total": 2, "successful": 1, "failed": 0 }, "created": false }
版本号(_version
)可用于跟踪文档已编入索引的次数。它的主要目的是容许乐观的并发控制,由于能够在索引请求中提供一个版本,若是提供的版本高于索引中的版本,ElasticSearch将只覆盖文档内容,ID值不变,版本号自动添加。
上面已经学习了索引新文档以及更新存在的文档。还看到了一个简单搜索请求的示例。若是只是想检索一个具备已知ID的索引,一个方法是搜索索引中的文档。另外一个简单而快速的方法是经过ID
,使用GET
来检索它。
简单的作法是向同一个URL发出一个GET请求,URL的ID部分是强制性的。经过ID从ElasticSearch中检索文档可发出URL的GET请求:http://localhost:9200/<index>/<type>/<id>
。
使用如下请求尝试获取电影信息:
curl -XGET "http://localhost:9200/movies/movie/1" -d''
执行结果以下所示 -
正以下图所看到的,结果对象包含与索引时所看到的相似的元数据,如索引,类型和版本信息。 最后最重要的是,它有一个名称为“_source
”的属性,它包含实际获取的文档信息。
关于GET没有什么可说的,由于它很简单,继续最后删除操做。
为了经过ID从索引中删除单个指定的文档,使用与获取索引文档相同的URL,只是这里将HTTP方法更改成DELETE
。
curl -XDELETE "http://localhost:9200/movies/movie/1" -d''
响应对象包含元数据方面的一些常见数据字段,以及名为“_found
”的属性,表示文档确实已找到而且操做成功。
在执行
DELETE
调用后切换回GET
,能够验证文档是否确实已删除。
在前面,已经介绍了在ElasticSearch索引中处理数据的基础知识,如今是时候进行核心功能的学习了。考虑到以前咱们删除索引中的全部文档,因此,在进行搜索学习以前,须要一些添加一些示例数据。使用如下这些请求和数据对象来建立索引。
curl -XPUT "http://localhost:9200/movies/movie/1" -d' { "title": "The Godfather", "director": "Francis Ford Coppola", "year": 1972, "genres": ["Crime", "Drama"] }' curl -XPUT "http://localhost:9200/movies/movie/2" -d' { "title": "Lawrence of Arabia", "director": "David Lean", "year": 1962, "genres": ["Adventure", "Biography", "Drama"] }' curl -XPUT "http://localhost:9200/movies/movie/3" -d' { "title": "To Kill a Mockingbird", "director": "Robert Mulligan", "year": 1962, "genres": ["Crime", "Drama", "Mystery"] }' curl -XPUT "http://localhost:9200/movies/movie/4" -d' { "title": "Apocalypse Now", "director": "Francis Ford Coppola", "year": 1979, "genres": ["Drama", "War"] }' curl -XPUT "http://localhost:9200/movies/movie/5" -d' { "title": "Kill Bill: Vol. 1", "director": "Quentin Tarantino", "year": 2003, "genres": ["Action", "Crime", "Thriller"] }' curl -XPUT "http://localhost:9200/movies/movie/6" -d' { "title": "The Assassination of Jesse James by the Coward Robert Ford", "director": "Andrew Dominik", "year": 2007, "genres": ["Biography", "Crime", "Drama"] }'
值得指出的是,ElasticSearch具备和端点(_bulk
)用于用单个请求索引多个文档,可是这超出了本教程的范围,这里只保持简单,使用六个单独的请求学习。
如今已经把一些电影信息放入了索引,能够经过搜索看看是否可找到它们。 为了使用ElasticSearch进行搜索,咱们使用_search
端点,可选择使用索引和类型。也就是说,按照如下模式向URL发出请求:<index>/<type>/_search
。其中,index
和type
都是可选的。
换句话说,为了搜索电影,能够对如下任一URL进行POST请求:
由于咱们只有一个单一的索引和单一的类型,因此怎么使用都不会有什么问题。为了简洁起见使用第一个URL。
若是只是发送一个请求到上面的URL,咱们会获得全部的电影信息。为了建立更有用的搜索请求,还须要向请求正文中提供查询。 请求正文是一个JSON对象,除了其它属性之外,它还要包含一个名称为“query
”的属性,这就可以使用ElasticSearch的查询DSL。
{ "query": { //Query DSL here } }
你可能想知道查询DSL是什么。它是ElasticSearch本身基于JSON的域特定语言,能够在其中表达查询和过滤器。想象ElasticSearch它像关系数据库的SQL。这里是ElasticSearch本身的文档解释它的一部分(英文好本身撸吧):
Think of the Query DSL as an AST of queries. Certain queries can contain other queries (like the bool query), other can contain filters (like the constant_score), and some can contain both a query and a filter (like the filtered). Each of those can contain any query of the list of queries or any filter from the list of filters, resulting in the ability to build quite complex (and interesting) queries. see more: http://www.elasticsearch.org/guide/reference/query-dsl/
查询DSL具备一长列不一样类型的查询可使用。 对于“普通”自由文本搜索,最有可能想使用一个名称为“查询字符串查询”。
查询字符串查询是一个高级查询,有不少不一样的选项,ElasticSearch将解析和转换为更简单的查询树。若是忽略了全部的可选参数,而且只须要给它一个字符串用于搜索,它能够很容易使用。
如今尝试在两部电影的标题中搜索有“kill”这个词的电影信息:
curl -XPOST "http://localhost:9200/_search" -d' { "query": { "query_string": { "query": "kill" } } }'
执行上面的请求并查看结果,以下所示 -
正如预期的,获得两个命中结果,每一个电影的标题中都带有“kill”单词。再看看另外一种状况,在特定字段中搜索。
在前面的例子中,使用了一个很是简单的查询,一个只有一个属性“query
”的查询字符串查询。 如前所述,查询字符串查询有一些能够指定设置,若是不使用,它将会使用默认的设置值。
这样的设置称为“fields”,可用于指定要搜索的字段列表。若是不使用“fields”字段,ElasticSearch查询将默认自动生成的名为“_all
”的特殊字段,来基于全部文档中的各个字段匹配搜索。
为了作到这一点,修改之前的搜索请求正文,以便查询字符串查询有一个fields
属性用来要搜索的字段数组:
curl -XPOST "http://localhost:9200/_search" -d' { "query": { "query_string": { "query": "ford", "fields": ["title"] } } }'
执行上面查询它,看看会有什么结果(应该只匹配到 1
行数据):
正如预期的获得一个命中,电影的标题中的单词“ford
”。如今,从查询中移除fields
属性,应该能匹配到 3
行数据:
前面已经介绍了几个简单的自由文本搜索查询。如今来看看另外一个示例,搜索“drama
”,不明确指定字段,以下查询 -
curl -XPOST "http://localhost:9200/_search" -d' { "query": { "query_string": { "query": "drama" } } }'
由于在索引中有五部电影在_all
字段(从类别字段)中包含单词“drama
”,因此获得了上述查询的5
个命中。 如今,想象一下,若是咱们想限制这些命中为只是1962
年发布的电影。要作到这点,须要应用一个过滤器,要求“year
”字段等于1962
。
要添加过滤器,修改搜索请求正文,以便当前的顶级查询(查询字符串查询)包含在过滤的查询中:
{ "query": { "filtered": { "query": { "query_string": { "query": "drama" } }, "filter": { //Filter to apply to the query } } } }
过滤的查询是具备两个属性(query
和filter
)的查询。执行时,它使用过滤器过滤查询的结果。要完成这样的查询还须要添加一个过滤器,要求year
字段的值为1962
。
ElasticSearch查询DSL有各类各样的过滤器可供选择。对于这个简单的状况,某个字段应该匹配一个特定的值,一个条件过滤器就能很好地完成工做。
"filter": { "term": { "year": 1962 } }
完整的搜索请求以下所示:
curl -XPOST "http://localhost:9200/_search" -d' { "query": { "filtered": { "query": { "query_string": { "query": "drama" } }, "filter": { "term": { "year": 1962 } } } } }'
当执行上面请求,只获得两个命中,这个两个命中的数据的 year
字段的值都是等于 1962
。
在上面的示例中,使用过滤器限制查询字符串查询的结果。若是想要作的是应用一个过滤器呢? 也就是说,咱们但愿全部电影符合必定的标准。
在这种状况下,咱们仍然在搜索请求正文中使用“query
”属性。可是,咱们不能只是添加一个过滤器,须要将它包装在某种查询中。
一个解决方案是修改当前的搜索请求,替换查询字符串 query
过滤查询中的match_all
查询,这是一个查询,只是匹配一切。相似下面这个:
curl -XPOST "http://localhost:9200/_search" -d' { "query": { "filtered": { "query": { "match_all": { } }, "filter": { "term": { "year": 1962 } } } } }'
另外一个更简单的方法是使用常数分数查询:
curl -XPOST "http://localhost:9200/_search" -d' { "query": { "constant_score": { "filter": { "term": { "year": 1962 } } } } }'
易百教程移动端:请扫描本页面底部(右侧)二维码并关注微信公众号,回复:"教程" 选择相关教程阅读或直接访问:http://m.yiibai.com 。