ES全文检索pdfwordtxt es全文检索 导入数据_ES全文检索pdfwordtxt


安装完成ElasticSearch环境,接下来就开始初步搭建一个查询服务。

为了方便理解,针对ES中关于数据的术语与MySQL和MongoDB的对应关系为:



需要注意的是, ElasticSearch的所有字段相当于都是索引过的(indexed)。

数据导入

在数据导入之前,需要先明确一下ES的数据格式要求。

在ES中,文档(Document)是一个JSON对象,不过特殊性在于,Document指顶层或者根对象,若是嵌套的JSON结构,可以理解成每个根对象的值,被序列化后保存在ES中。

通常的数据导入有以下几种方式:

  • 通过API实现数据录入
PUT /website/blog/123
{
  "title": "My first blog entry",
  "text":  "Just trying this out...",
  "date":  "2014/01/01"
}


其中,_index=website,_type=blog,_id=123。

若数据中没有可以作为UniqueID的列,导入过程中,可以通过ES自动生成ID,具体操作如下:


POST /website/blog/
{
  "title": "My second blog entry",
  "text":  "Still trying this out...",
  "date":  "2014/01/01"
}


通过这样的API接口,可以实现通过代码或脚本进行批量的数据录入。

若已经具有JSON格式的数据文件,可以通过文件直接进行数据导入,具体导入方式可参考:


curl -H "Content-Type: application/json" -XPOST "xx.xx.xx.xx:9200/index_name/_bulk?pretty&refresh" --data-binary "@esdata.json"
curl "xx.xx.xx.xx:9200/_cat/indices?v"


  • 通过ElasticDump实现数据录入

Elastic提供批量导入导出工具,不过需要额外进行安装。


npm install elasticdump -g


利用ElasticDump进行数据导出:


# 导出索引Mapping数据
elasticdump 
  --input=http://xx.xx.xx.xx:9200/index_name/index_type 
  --output=/data/my_index_mapping.json 
  --type=mapping 
# 导出索引数据
./bin/elasticdump 
  --input=http://xx.xx.xx.xx:9200/index_name/index_type 
  --output=/data/my_index.json 
  --type=data


利用ElasticDump进行数据导入:


# Mapping数据导入至索引
./bin/elasticdump 
  --output=http://xx.xx.xx.xx:9200/index_name 
  --input=/data/my_index_mapping.json 
  --type=mapping
# ES文档数据导入至索引
./bin/elasticdump 
  --output=http://xx.xx.xx.xx:9200/index_name 
  --input=/data/my_index.json  
  --type=data


由于我的数据均放在数据库中,这里使用了Python来操作ES,实现内容的填充。



# -*- coding: utf-8 -*-
import pandas as pd
from sqlalchemy import create_engine
from elasticsearch import Elasticsearch

sql = 'select `bookId`, `name`, `publish`, `author`, `seriesName`, `status` from t_book'
engine = create_engine('mysql+pymysql://root:welcome@localhost:3306/turing')

df = pd.read_sql_query(sql, engine)

es = Elasticsearch(['xx.xx.xx.xx:9200'])
result = es.indices.create(index='books', ignore=400)

for idx, item in df.iterrows():
    doc = {
        'name': item['name'],
        'publish': item['publish'],
        'author': item['author'],
	'seriesName': item['seriesName'],
	'status': item['status']
    }
    print(idx, doc)
    result = es.create(index='books', doc_type='sample', id=item['bookId'], body=doc)
    print(result)


小插曲 - cluster_block_exception

在使用Python进行数据导入的过程中,发现ES在报错,导致数据无法被导入。

报错内容如下:


elasticsearch.exceptions.TransportError: TransportError(429, 'cluster_block_exception', 'index [books] blocked by: [TOO_MANY_REQUESTS/12/index read-only / allow delete (api)];')


这时,我发现_index的状态为“read_only”,但是我手动修改该状态值发现无法修改成功,一直对外显示“read_only”。


curl -XPUT 'xx.xx.xx.xx:9200/books/_settings'  -H 'Content-Type: application/json' -d '{"index.blocks.read_only_allow_delete": null}'


最终Baidu了一下才知道,当磁盘剩余空间小于5%时,index会自动设置为read_only,并无法进行修改。处理的方法有两种:

  1. 清空磁盘空间,保证在5%,在执行命令,修改_index状态
  2. 通过修改配置文件,降低index可写入的磁盘下限

为了安全起见,我选择解决方案1,最终可以实现数据的正确导入。

数据搜索

在数据搜索前,可以先对数据是否导入成功进行一次确认。

通过_count,查看插入了多少条数据:


curl -XGET 'xx.xx.xx.xx:9200/index_name/index_type/_count' -H 'Content-Type: application/json'


使用空搜索,查看导入数据是否正确:


curl -XGET 'xx.xx.xx.xx:9200/index_name/index_type/_search' -H 'Content-Type: application/json'


当数据确认已经导入完成后,可以实现内容的检索,通常使用的检索方式有两种:

  • 轻量搜索

在最开始的时候说过,在ES中,相当于对所有的字段均建立了索引,因此可以很轻松的实现全文检索。

具体可以参考官网文档,“搜索——最基本的工具”。

例如:在type下全文检索“mary”


curl -XGET 'xx.xx.xx.xx:9200/index_name/index_type/_search?q=mary'


  • 请求体搜索

ES通过查询表达式(Query DSL)来支持更加灵活的查询方式,具体查询通过JSON格式进行。

具体可以参考官网文档,“请求体查询”。


{
    "bool": {
        "must":     { "match": { "tweet": "elasticsearch" }},
        "must_not": { "match": { "name":  "mary" }},
        "should":   { "match": { "tweet": "full text" }},
        "filter":   { "range": { "age" : { "gt" : 30 }} }
    }
}


在我的绘本数据中,期望可以实现通过绘本名称(name),作者(author),出版社(publish),绘本系列名称(series name)实现绘本搜索。具体代码如下所示:


# -*- coding: utf-8 -*-
from elasticsearch import Elasticsearch

qstr = "原则"
query = {
	"query": {
		"bool": {
			"must": [
				{
					"term": {
						"status": 1
					}
				}
			],
			"should": [
				{
					"match": {
						"name": {
							"query": qstr
						}
					}
				},
				{
					"match": {
						"author": {
							"query": qstr
						}
					}
				},
				{
					"match": {
						"publish": {
							"query": qstr
						}
					}
				},
				{
					"match": {
						"seriesName": {
							"query": qstr
						}
					}
				}
			]
		}
	},
	"from": 0,
	"size": 10
}

es = Elasticsearch(['192.168.1.135:9200'])
result = es.search(index="books", doc_type="sample", body=query)


在这段检索当中,会将输入的名称qstr分别在name,author,publish,seriesName上进行检索,同时要求对应的status字段必须为1,即已经被审核。

到这里,就完成了一个简单的图书检索服务,输出结果如下:


+-----------+----------------+----------------------------------------------------------------------+--------------------+------------------------+
|   Score   |      Name      |                                Author                                |      Publish       |       SeriesName       |
+-----------+----------------+----------------------------------------------------------------------+--------------------+------------------------+
| 17.760134 |     树真好     |              贾尼思·梅·伍德里 文 马可·塞蒙 图 舒杭丽 译              |    21世纪出版社    |           #            |
| 14.487474 |     真高兴     |                              木木树文化                              |    新时代出版社    |           #            |
| 13.899454 |    有你真好    |                            童悦早教  编著                            | 北方妇女儿童出版社 |    好孩子是夸出来的    |
| 13.111786 |  洗澡真好玩儿  |                               童悦早教                               | 北方妇女儿童出版社 |       卫生好习惯       |
| 12.519405 |     和平树     |                   (美)珍妮特·温特 文/图 徐泓 译                    |  北京联合出版公司  | 一个来自非洲的真实故事 |
| 12.476025 |   橡树图书馆   |                  (美)直子·巢冬符    著   李璐  译                  | 北方妇女儿童出版社 |       橡树图书馆       |
| 12.390741 |  失踪的小橘子  |    (法) 纳迪娜·布兰-科姆 文 (法) 奥利维耶·塔莱克 图 邢培健 译    |  新疆青少年出版社  |        有你真好        |
| 12.390741 | 来自远方的朋友 | (法) 纳迪娜·布兰-科姆   文 (法)  奥利维耶·塔莱克  图  邢培健  译 |  新疆青少年出版社  |        有你真好        |
| 12.390741 | 送你一场流星雨 |  (法) 纳迪娜·布兰-科姆  文  (法) 奥利维耶·塔莱克  图  邢培健 译  |  新疆青少年出版社  |        有你真好        |
| 11.763252 | 整体认读帮帮忙 |                         周霞 著 段张取艺 绘                          |   电子工业出版社   |       拼音真好玩       |
+-----------+----------------+----------------------------------------------------------------------+--------------------+------------------------+