Elasticsearch学习笔记(三)

建立一个员工目录

索引员工文档

在Elasticsearch中,文档归属于一种类型,而这些类型存在于索引中,我们可以画一些简单的对比图来类比传统关系型数据库

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

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

索引

索引就像是关系数据库中的数据库,它是相关文档存储的地方,index附属是indices或indexes

索引(动词)表示把一个文档存储到索引(名词)里,以便它可以北检索或者查询。这很像SQL中的insert 关键字,差别是,如果文档已经存在,新的文档将覆盖旧的文档。

倒排索引 传统数据库为特定列增加一个索引,例如B-Tree索引来加速检索。

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

  • 为每个员工的文档建立索引,每个文档包含响应员工的所有信息
  • 每个文档的类型为employee
  • employeee 类型归属于索引megacorp
  • megacorp 索引存储在Elasticsearch 集群中

实际上这些都是很容易的,尽管看起来有很多的步骤,我们通过一个命令执行完成的操作:

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 包含三部分信息:

名字说明
megacorp索引名
employee类型名
1员工ID

请求实体(JSON文档),包含了这个员工的所有信息。她的名字叫“John Smith”,25岁,喜欢攀岩。

很简单吧,它不需要你做额外的管理操作,比如创建索引或者定义每个字段的数据类型。我们能够直接索引,Elasticsearch已经内置所有的缺省设置,所有管理操作都是透明的。

接下来,让我们在目录中加入更多员工信息:

PUT /megacorp/employee/2
{
    "first_name":"Jane",
    "last_name":"Smith",
    "age":32,
    "about":"I like to collect rock albums",
    "interests":["music"]
}

PUT /megacorp/employee/3
{
    "first_name":"Douglas",
    "last_name":"FIr",
    "age":35,
    "about":"I like to build cabinets",
    "intersts":["forestry"]
}

简单搜索

GET 请求非常简单——你能轻松获取你想要的文档,让我们来进一步尝试一些东西,比如简单的搜索。

我们尝试一个最简单的搜索全部员工的请求:

GET /megacorp/employee/_search

你可以看到我们依然使用megacorp 索引和employee 类型,但是我们在结尾使用关键字_search 来取代原来的文档ID。响应内容的hit 数组中包含了我们所有的三个文档。默认情况下搜索会返回前10个结果。

{
    "took":6,
    "timed_out":false,
    "_shards":{...},
    "hit":{
        "total":3,
        "max_socre":1,
        "hits":[
            {
            "_index":"megacorp",
            "_type":"employee",
            "_id":"3",
            "_score":1,
            "_source":{
                "first_name":"Douglas",
                "last_name":"Fir",
                "age":35,
                "about":"I like to build cabinets",
                "insterests":["forestry"]
                }
            },
            {
            "_index":"megacorp",
            "_type":"employee",
            "_id":"1",
            "_score":1,
            "_source":{
                "first_name":"John",
                "last_name":"Smith",
                "age":25,
                "about":"I love to go rock climbing",
                "insterents":["sports","music"]
                }
            },
            {
            "_index":"megacorp",
            "_type":"employee",
            "_id":"2",
            "_score":1,
            "_source":{
                "first_name":"Jane",
                "last_name":"Smith",
                "age":32,
                "about":"I like to collect rock albums",
                "instersts":["music"]
                }
            }
        ]
    }
}

响应内容不仅会告诉我们哪些文档被匹配到,而且这些文档内容完整的被包含在其中,我们会给用户展示搜索结果时需要用到的所有信息都有了。

接下来,让我们搜索姓氏中包含Smith 的员工,要做到这一点,我们将在命令中使用轻量级的搜索方法,这种方法常北称作查询字符串搜索,因为我们像传递URL参数一样去传递查询语句:

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",
                    "insterests":["music"]
                    }
                }
            ]
        }
}

使用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 语句(查询类型之一)。

更复杂的搜索

我们让搜索稍微在变的复杂一些,我们依旧想要找到姓氏为“Smith”的员工,但是我们只想得到年龄大于30岁的员工。我们的语句将添加过滤器(filter),它使得我们高效率的执行一个结构化搜索:

GET /megacorp/employee/_search
{
    "query":{
        "filtered":{
            "filter":{
                "range":{
                    "age":{"gt":38}<1>
                }
            },
            "query":{
                "match":{
                    "last_name":"smith"<2>
                }
            }
        }
    }
}

<1>这部分查询属于区间过滤器(range filter),它用于查找所有年龄大于30岁的数据,gt为“greater than”的缩写
<2>这部分查询与之前的match语句一致

现在不要担心语法太多,我们将会在以后详细的讨论,你只要知道我们添加了一个过滤器filter用于执行区间搜索,然后重复利用了之前的match语句。现在我们搜索结果之显示了一个32岁且名字是“Jane Smith”的员工:

{
...
"hits": {
    "total": 1,
    "max_score": 0.30685282,
    "hits": [
            {
                ...
                "_source": {
                "first_name": "Jane",
                "last_name": "Smith",
                "age": 32,
                "about": "I like to collect rock albums",
                "interests": [ "music" ]
                }
            }
        ]
    }
}

全文搜索

到目前为止,搜索都很简单:搜索特定的名字,通过年龄筛选。让我们尝试一种更高级的搜索,全文搜索——一种传统数据库很难实现的功能。

我们将会搜索所有喜欢“rock climbing”的员工:

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

你可以看到我们使用了之前的match 查询,从about 字段中搜索“rock climbing”,我们得到两个匹配文档;

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

<1><2>结果相关性评分

默认情况下,Elasticsearch根据结果相关性评分来对结果集进行排序,所谓结果相关性评分,就是文档与查询条件的匹配程度。很显然,排名第一的John Smithabout 字段明确的写道rock climbing.

但是为什么Jane smith 也会出现在结果里呢?原因是rock 字段中被提及了。因为只有“rock”被提及而“climing”没有,所以她的_score 要低于John。

这个例子很好的解释了Elasticsearch如何在各种文本字段中进行全文搜索,并且返回相关性最大的结果集。相关性的概念非常重要,而这个概念在传统关系行数据库中是不可想象的,因为传统数据库对记录的查询只有匹配或者不匹配。

短语搜索

目前我们可以在字段中搜索单独的一个词,这挺好的,但是有时候你想要确切的匹配若干个单词或者短语。例如我们想要查询同时包含“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":{
                "frist_name":"John",
                "last_name":"Smith",
                "age":25,
                "about":"I love to go rock climbing",
                "interests":["sports","music"]
                }
            }
        ]
    }
}

高亮我们的搜索

很多应用喜欢从每个搜索结果中高亮匹配到的关键字,这样用户可以知道为什么这些文档和查询相匹配。在Elasticsearch中高亮片段是非常容易的。

让我们在之前的语句上增加highlight 参数

GET /megacorp/employee/_search
{
    "query":{
        "match_phrase":{
            "about":"rock climbing"
        }
    },
    "highlight":{
        "fields":{
            "about":{}
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值