ES一| es的一些基本概念及入门操作

免责声明:本专栏的内容都是在读了《Elasticsearch权威指南( 中文版)》书籍后整理的读后感及部分内容笔记,具体内容请查阅原著内容。

前言:

为了搜索, 你懂的Elasticsearch是一个基于Apache Lucene(TM)的开源搜索引擎。 无论在开源还是专有领域,Lucene可以被认为是迄今为止最先进、 性能最好的、 功能最全的搜索引擎库。

但是, Lucene只是一个库。 想要使用它, 你必须使用Java来作为开发语言并将其直接集成到你的应用中, 更糟糕的是, Lucene非常复杂, 你需要深入了解检索的相关知识来理解它是如何工作的。

Elasticsearch也使用Java开发并使用Lucene作为其核心来实现所有索引和搜索的功能, 但是它的目的是通过简单的 RESTful API 来隐藏Lucene的复杂性, 从而让全文搜索变得简单。

一、基本概念及特性

  • 面向文档

应用中的对象很少只是简单的键值列表, 更多时候它拥有复杂的数据结构, 比如包含日期、地理位置、 另一个对象或者数组。总有一天你会想到把这些对象存储到数据库中。 将这些数据保存到由行和列组成的关系数据库中, 就好像是把一个丰富, 信息表现力强的对象拆散了放入一个非常大的表格中: 你不得不拆散对象以适应表模式( 通常一列表示一个字段) , 然后又不得不在查询的时候重建它们。

Elasticsearch是面向文档(document oriented)的, 这意味着它可以存储整个对象或文档(document)。 然而它不仅仅是存储, 还会索引(index)每个文档的内容使之可以被搜索。 在Elasticsearch中, 你可以对文档( 而非成行成列的数据) 进行索引、 搜索、 排序、 过滤。 这种理解数据的方式与以往完全不同, 这也是Elasticsearch能够执行复杂的全文搜索的原因之一。

  • JSON

ELasticsearch使用Javascript对象符号(JavaScript Object Notation), 也就是JSON, 作为文档序列化格式。 JSON现在已经被大多语言所支持, 而且已经成为NoSQL领域的标准格式。 它简洁、 简单且容易阅读。以下使用JSON文档来表示一个用户对象:

{
    "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"
}

尽管原始的 user 对象很复杂, 但它的结构和对象的含义已经被完整的体现在JSON中了, 在Elasticsearch中将对象转化为JSON并做索引要比在表结构中做相同的事情简单的多。

  • Java API

基于HTTP协议, 以JSON为数据交互格式的RESTful API。

Elasticsearch为Java用户提供了两种内置客户端:节点客户端(node client):节点客户端以无数据节点(none data node)身份加入集群, 换言之, 它自己不存储任何数据,但是它知道数据在集群中的具体位置, 并且能够直接转发请求到对应的节点上。传输客户端(Transport client):这个更轻量的传输客户端能够发送请求到远程集群。 它自己不加入集群, 只是简单转发请求给集群中的节点。两个Java客户端都通过9300端口与集群交互, 使用Elasticsearch传输协议(ElasticsearchTransport Protocol)。 集群中的节点之间也通过9300端口进行通信。 如果此端口未开放, 你的节点将不能组成集群。

  • 数据组织形式

在Elasticsearch中存储数据的行为就叫做索引(indexing), 不过在索引之前, 我们需要明确数据应该存储在哪里。在Elasticsearch中, 文档归属于一种类型(type),而这些类型存在于索引(index)中, 我们可以画一些简单的对比图来类比传统关系型数据库:

Relational DB -> Databases -> Tables -> Rows -> Columns
Elasticsearch -> Indices -> Types -> Documents -> Fields

Elasticsearch集群可以包含多个索引(indices)( 数据库) , 每一个索引可以包含多个类型(types)( 表) , 每一个类型包含多个文档(documents)( 行) , 然后每个文档包含多个字段(Fields)( 列) 。
 

二、基本操作

以创建和检索一个员工信息索引为例子:

  • 插入数据

为了创建员工目录, 我们将进行如下插入操作:

PUT /megacorp/employee/1
{
"first_name" : "John",
"last_name" : "Smith",
"age" : 25,
"about" : "I love to go rock climbing",
"interests": [ "sports", "music" ]
}

我们看到path: /megacorp/employee/1 包含三部分信息:

请求实体( JSON文档) , 包含了这个员工的所有信息。 他的名字叫“John Smith”, 25岁, 喜欢攀岩。我们能够直接索引文档, Elasticsearch已经内置所有的缺省设置, 所有管理操作都是透明的。

  • 检索文档
  1. 简单搜索

我们的第一个需求是能够检索单个员工的信息。对于Elasticsearch来说非常简单。 我们只要执行HTTP GET请求并指出文档的“地址”——索引、 类型和ID既可。 根据这三部分信息, 我们就可以返回原始JSON文档:

按id搜索结果,执行命令:

GET /megacorp/employee/1

结果:

{
"_index" : "megacorp",
"_type" : "employee",
"_id" : "1",
"_version" : 1,
"found" : true,
"_source" : {
"first_name" : "John",
"last_name" : "Smith",
"age" : 25,
"about" : "I love to go rock climbing",
"interests": [ "sports", "music" ]
}
}

我们通过HTTP方法 GET 来检索文档, 同样的, 我们可以使用 DELETE 方法删除文档, 使用 HEAD 方法检查某文档是否存在。 如果想更新已存在的文档, 我们只需再 PUT 一次。

查询所有结果,执行命令:

GET /megacorp/employee/_search

简单的按条件搜索:

GET /megacorp/employee/_search?q=last_name:Smith

在请求中依旧使用 _search 关键字, 然后将查询语句传递给参数 q= 。 这样就可以得到所有姓氏为Smith的结果:

{
...
"hits": {
"total": 2,
"max_score": 0.30685282,
"hits": [
{
...
"_source": {
"first_name": "John",
"last_name": "Smith",
"age": 25,
"about": "I love to go rock climbing",
"interests": [ "sports", "music" ]
}
},
{
...
"_source": {
"first_name": "Jane",
"last_name": "Smith",
"age": 32,
"about": "I like to collect rock albums",
"interests": [ "music" ]
}
}
]
}
}

但是这种方法在参数量过多的情况下不太适用,所以一般很少使用这种方式,而是使用更加高效的DSL查询。

2. 使用DSL语句查询

查询字符串搜索便于通过命令行完成特定(ad hoc)的搜索, 但是它也有局限性 。 Elasticsearch提供丰富且灵活的查询语言叫做DSL查询(Query DSL),它允许你构建更加复杂、 强大的查询。DSL(Domain Specific Language特定领域语言)以JSON请求体的形式出现。 我们可以这样表示之前关于“Smith”的查询:

GET /megacorp/employee/_search
{
    "query" : {
        "match" : {
            "last_name" : "Smith"
        }
    }
}

这会返回与之前查询相同的结果。 你可以看到有些东西改变了, 我们不再使用查询字符串(query string)做为参数, 而是使用请求体代替。 这个请求体使用JSON表示, 其中使用了 match 语句。

3. 短语搜索

目前我们可以在字段中搜索单独的一个词, 这挺好的, 但是有时候你想要确切的匹配若干个单词或者短语(phrases)。 例如我们想要查询同时包含"rock"和"climbing"( 并且是相邻的) 的员工记录。

要做到这个, 我们只要将 match 查询变更为 match_phrase 查询即可:

GET /megacorp/employee/_search
{
    "query" : {
        "match_phrase" : { //短语搜索
            "about" : "rock climbing"
        }
    }
}

毫无疑问, 该查询返回John Smith的文档:

{
...
"hits": {
"total": 1,
"max_score": 0.23013961,
"hits": [
{
...
"_score": 0.23013961,
"_source": {
"first_name": "John",
"last_name": "Smith",
"age": 25,
"about": "I love to go rock climbing",
"interests": [ "sports", "music" ]
}
}
]
}
}

4. 全文及高亮搜索

让我们尝试一种更高级的搜索, 全文搜索——一种传统数据库很难实现的功能。我们将会搜索所有喜欢“rock climbing”的员工,同时从每个搜索结果中高亮(highlight)匹配到的关键字, 这样用户可以知道为什么这些文档和查询相匹配。

GET /megacorp/employee/_search
{
"query" : {
"match" : {
"about" : "rock climbing"
}
},
"highlight": {
"fields" : {
"about" : {}
}
}
}

当我们运行这个语句时, 会命中与之前相同的结果, 但是在返回结果中会有一个新的部分叫做 highlight , 这里包含了来自 about 字段中的文本, 并且用 <em></em> 来标识匹配到的单词。

{
...
"hits": {
"total": 1,
"max_score": 0.23013961,
"hits": [
{
...
"_score": 0.23013961,
"_source": {
"first_name": "John",
"last_name": "Smith",
"age": 25,
"about": "I love to go rock climbing",
"interests": [ "sports", "music" ]
},
"highlight": {
"about": [
"I love to go <em>rock</em> <em>climbing</em>" <1>
]
}
}
]
}
}
  • 聚合功能

还有一个需求需要完成: 允许管理者在职员目录中进行一些分析。 Elasticsearch有一个功能叫做聚合(aggregations), 它允许你在数据上生成复杂的分析统计。 它很像SQL中的 GROUP BY 但是功能更强大。举个例子, 让我们找到所有职员中最大的共同点( 兴趣爱好) 是什么:

GET /megacorp/employee/_search
{
    "aggs": {
        "all_interests": {
            "terms": { "field": "interests" }
        }
    }
}

暂时先忽略语法只看查询结果:

{
...
"hits": { ... },
"aggregations": {
"all_interests": {
"buckets": [
{
"key": "music",
"doc_count": 2
},
{
"key": "forestry",
"doc_count": 1
},
{
"key": "sports",
"doc_count": 1
}
]
}
}
}

我们可以看到两个职员对音乐有兴趣, 一个喜欢林学, 一个喜欢运动。 这些数据并没有被预先计算好, 它们是实时的从匹配查询语句的文档中动态计算生成的。

小结:

望这个简短的教程能够很好的描述Elasticsearch的功能。 当然这只是一些皮毛, 为了保持简短, 还有很多的特性未提及——像推荐、 定位、 渗透、 模糊以及部分匹配等。 但这也突出了构建高级搜索功能是多么的容易。 无需配置, 只需要添加数据然后开始搜索!    ------《Elasticsearch权威指南》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值