Elasticsearch基础知识提升

373 阅读3分钟

这是我参与8月更文挑战的第15天,活动详情查看:8月更文挑战

简介

Elasticsearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口。Elasticsearch是用Java语言开发的,并作为Apache许可条款下的开放源码发布,是一种流行的企业级搜索引擎。Elasticsearch用于云计算中,能够达到实时搜索,稳定,可靠,快速,安装使用方便。官方客户端在Java、.NET(C#)、PHP、Python、Apache Groovy、Ruby和许多其他语言中都是可用的。根据DB-Engines的排名显示,Elasticsearch是最受欢迎的企业搜索引擎,其次是Apache Solr,也是基于Lucene。

ES核心概念

ElasticSearch是面向文档型的数据库,一条数据在这里就是一个文档。比如:

{
    "name" :     "John",
    "sex" :      "Male",
    "age" :      25,
    "birthDate": "1990/05/01",
    "about" :    "I love to go rock climbing",
    "interests": [ "sports", "music" ]
}

在MySql中这样的数据存储容易想到建立一张User表,其中有一些字段,而在es中就是一个文档,文档会属于一个User类型,各种各样的类型存储于一个索引中。下表是关系型数据库和es的疏于对照表:

关系型数据库ElasticSearch
数据库索引
type
document
field

es中可以包含多个索引(数据库),每个索引中可以包含多个类型(表),每个类型下又包含多个文档(行),每个文档又包含多个字段(列)。

物理设计:

es在后台把每个索引划分成多个分片,每个分片可以在集群中的不同服务器中转移。

逻辑设计:

一个索引类型,包含多个文档,当我们索引一篇文档时,可以通过这样的顺序找到他: 索引-》类型-》文档id(该id实际是个字符串),通过这个组合我们就能索引到某个具体的文档。

创建 Index

创建一个名为 news 的索引:
from elasticsearch import Elasticsearch
 
es = Elasticsearch()
result = es.indices.create(index='news', ignore=400)
print(result)

如果创建成功,会返回如下结果:

{
    "acknowledged":true,
    "shards_acknowledged":true,
    "index":"news"
}

返回结果是 JSON 格式,其中的 acknowledged 字段表示创建操作执行成功。

但这时如果我们再把代码执行一次的话,就会返回如下结果:

{
    "error":{
        "root_cause":[
            {
                "type":"resource_already_exists_exception",
                "reason":"index [news/QM6yz2W8QE-bflKhc5oThw] already exists",
                "index_uuid":"QM6yz2W8QE-bflKhc5oThw",
                "index":"news"
            }
        ],
        "type":"resource_already_exists_exception",
        "reason":"index [news/QM6yz2W8QE-bflKhc5oThw] already exists",
        "index_uuid":"QM6yz2W8QE-bflKhc5oThw",
        "index":"news"
    },
    "status":400
}

它提示创建失败,status 状态码是 400,错误原因是 Index 已经存在了。

注意这里我们的代码里面使用了 ignore 参数为 400,这说明如果返回结果是 400 的话,就忽略这个错误不会报错,程序不会执行抛出异常。

假如我们不加 ignore 这个参数的话:

es = Elasticsearch()
result = es.indices.create(index='news')
print(result)

再次执行就会报错了:

raise HTTP_EXCEPTIONS.get(status_code, TransportError)(status_code, error_message, additional_info)
elasticsearch.exceptions.RequestError: TransportError(400, 'resource_already_exists_exception', 'index [news/QM6yz2W8QE-bflKhc5oThw] already exists')

这样程序的执行就会出现问题,所以说,我们需要善用 ignore 参数,把一些意外情况排除,这样可以保证程序的正常执行而不会中断。

删除 Index

删除 Index 也是类似的,代码如下:

from elasticsearch import Elasticsearch
 
es = Elasticsearch()
result = es.indices.delete(index='news', ignore=[404])
print(result)

这里也是使用了 ignore 参数,来忽略 Index 不存在而删除失败导致程序中断的问题。

如果删除成功,会输出如下结果:

{
    "acknowledged":true
}

插入数据

Elasticsearch 就像 MongoDB 一样,在插入数据的时候可以直接插入结构化字典数据。

from elasticsearch import Elasticsearch

es = Elasticsearch()
es.indices.create(index='news', ignore=400)

data = {'title': '美国留给伊拉克的是个烂摊子吗', 'url': 'http://view.news.qq.com/zt2011/usa_iraq/index.htm'}
result = es.create(index='news', id=1, body=data)
print(result)

调用 create() 方法时,index 参数代表了索引名称,body 则代表了文档具体内容,id 则是数据的唯一标识 ID。

运行结果如下:

{
    "_index":"news",
    "_type":"_doc",
    "_id":"1",
    "_version":1,
    "result":"created",
    "_shards":{
        "total":2,
        "successful":1,
        "failed":0
    },
    "_seq_no":0,
    "_primary_term":1
}

结果中 result 字段为 created,代表该数据插入成功。