热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

ElasticSearch的开篇构建一个简单的全文搜索

文章目录

    • ElasticSearch是什么?
    • ElasticSearch能做些什么?
    • ElasticSearch怎么用?
      • 1. 数据,数据,数据
      • 2.建立索引(index)
      • 3.搜索,搜索,搜索
    • 总结

ElasticSearch是什么?

ElasticSearch是一个基于Lucene的搜索服务器。它和Lucene之间的关系在下文的介绍中会通过流图来详细分析的。现在只要知道,ES(ElasticSearch)是基于Lucene开发的一个搜索服务器。如果就那么简单的话,ES就不会像现在那么流行了,它还提供了一个分布式多用户能力的全文搜索引擎。全文搜索这是Lucene本身就具备的,而分布式这个东西就非常有用了。像现在的大数据平台Hadoop,Spark基本都是分布式的,分布式计算的好处在这里就不细讲了。有了ES就能和这些大数据平台无缝衔接,这也是ES流行的原因之一吧。
此外,ElasticSearch提供了RESTful web的接口,这让ES非常容易的连接到很多平台之上,我们只需要通过与服务器端口之间的数据交互就能轻易地使用ES。ES是基于java开发,并提供python,PHP,go等多语言的api。本文对ES的开发是完全基于python完成。
可能你没有使用过ES,或者第一次接触ES,但是你一定使用过ES的服务,现在很多流行的应用都是基于ES开发的,比如github,***,***,抖音中的一些搜索服务。类似的其实还有更多,并不是每家公司有能力开发出一套像百度,谷歌这样完整的搜索引擎。

ElasticSearch能做些什么?

这一部分才是我学习ES最关心的地方,不要花里胡哨的说那么多,你到底能做什么呐?(show me your ability)。

  1. 首先讲的当然是搜索,如果你想给网站添加上搜索功能,运行速度还要匹配到企业级,且不怎么想从零开始搭建,不怎么费事配置,当然要开源免费。网站嘛,使用json通过http索引数据最好,ElasticSearch就能完美匹配以上的问题。
  2. 有可能起初数据没那么多,我们只需要一台服务器即可,但是如果随着应用的积累,数据量越来越大,搜索服务器就需要从一台扩展到数百台,这时还需要实时,ElasticSearch还是能解决这些问题。
  3. 还有其他更多的应用,目前我对ES理解还是比较浅薄,希望在以后的探索中能更多的了解ES。

ElasticSearch怎么用?

ElasticSearch的开篇-构建一个简单的全文搜索
上图很清晰的介绍了ElasticSearch和Lucene之间的关系,作为开发者,我们只需要将数据和ES与用户交互部分完成即可。其中数据可以来自两部分,一部分是通过爬虫实时爬取,那就可以真正的实现一个搜索引擎了,另外可以将本地数据导入到ES中。

1. 数据,数据,数据

按照上图的分析,使用ElasticSearch,第一步就是需要建立ES能用的数据,ES其实就是一个面向文档型的数据库,一条数据在ES中就是一个文档,用json的格式对文档进行序列化。比如一条用户的数据如下所示:

{
    "name" :     "fangfang",
    "sex" :      "Female",
    "age" :      21,
    "birthDate": "1998/05/01",
    "about" :    "I love sing,dance,basketball and hip",
    "interests": [ "basketball", "music" ]
}

用关系型数据库的话,最直接的想法就是建立一个User表,然后建立相应的字段等。
在ES中这就是一个文档,当然这个文档会属于一个User的类型,各种各样的类型存在于一个索引当中。这里有一份简易的将Elasticsearch和关系型数据术语对照表:

关系数据库 数据库
ES 索引(index) 类型(type) 文档 字段(fields)

一目了然吧,一个ES集群中可以包含多个索引(数据库),一个索引也可以对应了多个类型(表),这些类型中包含了很多的文档(行),然后每个文档中又包含了很多的字段(列)。
现在清楚了吧,要想使用ES,首先我们首先需要json格式的数据。有了json数据之后,怎么把这些数据存储到ES中呐?

2.建立索引(index)

这篇文章不会详细讲解索引是什么?以及ES为什么要用索引的方式来存储数据,现在只要知道,这一切都是为了搜索服务的,也就是说,这一切都是为了提高搜索的性能

#coding:utf-8
import os
import time 
from os import walk
from elasticsearch import Elasticsearch
from elasticsearch.helpers import bulk
from elasticsearch import helpers
from datetime import datetime 
import json

class ElasticObj:
	def __init__(self,index_name,index_type,ip="127.0.0.1"):
		"""
		param 
			index_name:索引名称
			index_type:索引类型

		"""
		self.index_name = index_name
		self.index_type = index_type
		self.es = Elasticsearch([ip],http_auth=('elastic','password'),port = 9200)

	def set_index(self,index_name):
		"""
		索引设置
		"""
		_index_settings={
		"settings":{
    		"number_of_shards": "6",
    		"number_of_replicas": "1",  
  		}
		}

		if self.es.indices.exists(index = self.index_name) is not True:
			res =  self.es.indices.create(index = self.index_name,body = _index_settings)
			print(res)
	def create_index(self,index_name='user_test1',index_type='user_type_test1'):
		"""
		创建索引,索引名称为user,索引类型为user_type
		"""
		#创建映射
		_index_mappings={
					"properties": {
						"user_name": {
						"type": "text",
						"analyzer":"ik_max_word",
						"search_analyzer":"ik_max_word"
					}
				}
		}
		if self.es.indices.exists(index = self.index_name) is   True:
			res = self.es.indices.put_mapping(doc_type=index_type,index=self.index_name,body=_index_mappings)
			print(res)

	def index_data(self):
		"""
		存储样例数据到es

		"""
		index_list = [
			{ 	
				
				"user_name":"支付宝"
				
			},
			{ 	
				
				"user_name":"支付宝天猫"
				
			},
			{ 	
				
				"user_name":"支付宝淘宝"
				
			},

			{
				
				"user_name":"百度"

			},
				{
				
				"user_name":"百度金融"

			},
				{
				
				"user_name":"百度小满"

			}
		]
		id =1;
		for item in index_list:
			res = self.es.index(index=self.index_name,doc_type=self.index_type,body=item,id = id)
			id+=1
			print(res)


	def bulk_index_data(self,user_path='D:/rookieproject/user_name/user-Names.txt'):
		"""
		批量建立索引数据
		user_path:对应的user_name文件
		return:

		"""
		#result = {}
		lines=[]
		with open(user_path,'r',encoding='UTF-8') as f:
			for line in f.readlines():
			#results['user_name']=line.strip()
				#lines.append({"user_name":line.strip()})
				lines.append({"user_name":line.strip()})


		actiOns=  []
		i = 1
		for line in lines:
			action = {
				"_index":self.index_name,
				"_type":self.index_type,
				"_id":i,
				"_source":{
					"user_name":line['user_name']
				}
			}
			i+=1
			actions.append(action)
		sucess,_ = bulk(self.es,actions,index=self.index_name,raise_on_error = True,request_timeout=100)
		print(sucess)

	def delete_index_data(self,id):
		"""
		删除索引中的一条数据
		param id 
		return :
		"""
		res = self.es.delete(index = self.index_name,doc_type=self.index_type,id = id)
		#删除结果
		print(res)
	def get_data_id(self,id):
		res = self.es.get(index = self.index_name,doc_type = self.index_type,id = id)
		print(res['_source'])

		print("-----------------------------------------------")
		print(res)
		#for hit in res['hits']:
		#	print(hit['_source']['user_name'],hit['_source']['user_name'])

	def get_data_by_query(self,query_term="支付宝"):

		result = {}
		ans_li=[]
		score_li=[]
		ress  =""
		
		doc = {	
		"query":{
			"match":{
				"user_name":{
					"query":query_term,
					"analyzer":"ik_max_word"
				}

			}
		},

			"highlight": {

				"fields": {
				"user_name":{}
		 		}
			}

		}

		_searched = self.es.search(index = self.index_name,doc_type = self.index_type,body = doc,search_type='query_then_fetch')

		print(_searched)
		
		for hit in _searched['hits']['hits']:
			ress=ress+hit['highlight']['user_name'][0]+"
" ans_li.append(hit['_source']['user_name']) score_li.append(hit['_score']) print(hit['_source']['user_name'],hit['_score']) print("===============================================") result['ans'] = ans_li result['score'] = score_li return result,ress if __name__=="__main__": obj = ElasticObj("user_ik_base","ik_base_type") #obj = ElasticObj("user","user_type") #obj.set_index("user_ik_base") #obj.create_index("user_ik_base","ik_base_type") #obj.index_data() #obj.get_data_id(1) #obj.bulk_index_data() for i in range(100): print("输入公司名称:") user_name = input() #print("搜索结果:") print("===============================================") obj.get_data_by_query(user_name) #obj.bulk_index_data()

先上代码,通过python与ES实现交互,以上代码需要安装python库elasticsearch,下载与你安装的对应的ES版本即可。
当然还需要安装elasticsearch
按照下面的步骤建立索引:

  1. settings,建立index的settings,主要是修改分片和副本数,这个在以后的篇章中将详细介绍。对应的代码:
def set_index(self,index_name):
		"""
		索引设置
		"""
		_index_settings={
		"settings":{
    		"number_of_shards": "6",
    		"number_of_replicas": "1",  
  		}
		}

		if self.es.indices.exists(index = self.index_name) is not True:
			res =  self.es.indices.create(index = self.index_name,body = _index_settings)
			print(res)
  1. mappings,指定index中的相关的字段和类型,还有分词器。中文中常用的分词器有ik,jieba,海量等,对应的代码:
def create_index(self,index_name='user_test1',index_type='user_type_test1'):
		"""
		创建索引,索引名称为user,索引类型为user_type
		"""
		#创建映射
		_index_mappings={
					"properties": {
						"user_name": {
						"type": "text",
						"analyzer":"ik_max_word",
						"search_analyzer":"ik_max_word"
					}
				}
		}
		if self.es.indices.exists(index = self.index_name) is   True:
			res = self.es.indices.put_mapping(doc_type=index_type,index=self.index_name,body=_index_mappings)
			print(res)
  1. 建立索引,这部分就是向ES中导入数据。有单个导入数据和批量导入数据(bulk)。
    单个导入数据对应的代码:
def index_data(self):
		"""
		存储样例数据到es

		"""
		index_list = [
			{ 	
				
				"user_name":"支付宝"
				
			},
			{ 	
				
				"user_name":"支付宝天猫"
				
			},
			{ 	
				
				"user_name":"支付宝淘宝"
				
			},

			{
				
				"user_name":"百度"

			},
				{
				
				"user_name":"百度金融"

			},
				{
				
				"user_name":"百度小满"

			}
		]
		id =1;
		for item in index_list:
			res = self.es.index(index=self.index_name,doc_type=self.index_type,body=item,id = id)
			id+=1
			print(res)

批量导入数据对应的代码:

def bulk_index_data(self,user_path='D:/rookieproject/user_name/user-Names-Corpus.txt'):
		"""
		批量建立索引数据
		user_path:user_name对应的文件
		return:
		"""
		#result = {}
		lines=[]
		with open(user_path,'r',encoding='UTF-8') as f:
			for line in f.readlines():
			#results['user_name']=line.strip()
				#lines.append({"user_name":line.strip()})
				lines.append({"user_name":line.strip()})
		actiOns=  []
		i = 1
		for line in lines:
			action = {
				"_index":self.index_name,
				"_type":self.index_type,
				"_id":i,
				"_source":{
					"user_name":line['user_name']
				}
			}
			i+=1
			actions.append(action)
		sucess,_ = bulk(self.es,actions,index=self.index_name,raise_on_error = True,request_timeout=100)
		print(sucess)

3.搜索,搜索,搜索

搜索对应的代码:

def get_data_by_query(self,query_term="支付宝"):

		result = {}
		ans_li=[]
		score_li=[]
		ress  =""
		doc = {	
		"query":{
			"match":{
				"user_name":{
					"query":query_term,
					"analyzer":"ik_max_word"
				}
			}
		},
			"highlight": {

				"fields": {
				"user_name":{}
		 		}
			}
		}
		_searched = self.es.search(index = self.index_name,doc_type = self.index_type,body = doc,search_type='query_then_fetch')

		print(_searched)
		
		for hit in _searched['hits']['hits']:
			ress=ress+hit['highlight']['user_name'][0]+"
" ans_li.append(hit['_source']['user_name']) score_li.append(hit['_score']) print(hit['_source']['user_name'],hit['_score']) print("===============================================") result['ans'] = ans_li result['score'] = score_li return result,ress

总结

本文介绍了ES的基本原理,其中索引,类型,文档和字段和关系型数据库相对应。按照以上的步骤可以快速建立一个针对user_name的全文搜索,本文采用了ik分词器,针对中文分词器的介绍在以后会介绍。
本文针对ES的操作全部通过python api来完成,可以通过bulk接口快速建立大批量文档的索引。
参考:
[1]: https://www.cnblogs.com/sha0830/p/8000242.html
[2]: https://www.elastic.co/cn/products/elasticsearch


推荐阅读
  • Elasticsearch 嵌套调用中动态类导致数据返回异常分析与解决方案 ... [详细]
  • 本文整理了Java中org.apache.hadoop.io.ByteWritable.<init>()方法的一些代码示例,展示了ByteWri ... [详细]
  • Python:新浪微博API初试
    {想在微博上抓点数据进行分析,费了一天多的时间,才终于找到点头绪,整理一下。}目录:一注册创建应用获取认证和授权二新浪微博pythonsdk下载和安装三简 ... [详细]
  • electronvue使用electronupdater实现自动更新
    今天呢,给大家带来一篇干货满满的electron-vue自动升级的教程,话不多说,开始我的表演!配置文件package.jsonbu ... [详细]
  • 优雅地记录API调用时长
    本文旨在探讨如何高效且优雅地记录API接口的调用时长,通过实际案例和代码示例,帮助开发者理解并实施这一技术,提高系统的可观测性和调试效率。 ... [详细]
  • 本文回顾了作者在求职阿里和腾讯实习生过程中,从最初的迷茫到最后成功获得Offer的心路历程。文中不仅分享了个人的面试经历,还提供了宝贵的面试准备建议和技巧。 ... [详细]
  • 从理想主义者的内心深处萌发的技术信仰,推动了云原生技术在全球范围内的快速发展。本文将带你深入了解阿里巴巴在开源领域的贡献与成就。 ... [详细]
  • 精选10款Python框架助力并行与分布式机器学习
    随着神经网络模型的不断深化和复杂化,训练这些模型变得愈发具有挑战性,不仅需要处理大量的权重,还必须克服内存限制等问题。本文将介绍10款优秀的Python框架,帮助开发者高效地实现分布式和并行化的深度学习模型训练。 ... [详细]
  • 流处理中的计数挑战与解决方案
    本文探讨了在流处理中进行计数的各种技术和挑战,并基于作者在2016年圣何塞举行的Hadoop World大会上的演讲进行了深入分析。文章不仅介绍了传统批处理和Lambda架构的局限性,还详细探讨了流处理架构的优势及其在现代大数据应用中的重要作用。 ... [详细]
  • 从0到1搭建大数据平台
    从0到1搭建大数据平台 ... [详细]
  • 为了在Hadoop 2.7.2中实现对Snappy压缩和解压功能的原生支持,本文详细介绍了如何重新编译Hadoop源代码,并优化其Native编译过程。通过这一优化,可以显著提升数据处理的效率和性能。此外,还探讨了编译过程中可能遇到的问题及其解决方案,为用户提供了一套完整的操作指南。 ... [详细]
  • 在List和Set集合中存储Object类型的数据元素 ... [详细]
  • 本书《.NET Core 2.* 开发者指南》是面向开发者的全面学习与实践手册,涵盖了从基础到高级的各个层面。书中详细解析了 .NET Core 的核心概念,包括如何创建 .NET Core 网站,并通过视频教程直观展示操作过程。此外,还深入探讨了 Startup 类的作用、项目目录结构的组织方式以及如何在应用中使用静态文件等内容。对于希望深入了解 .NET Core 架构和开发技巧的开发者来说,本书提供了丰富的实践案例和详尽的技术指导。 ... [详细]
  • 掌握 esrally 三步骤:高效执行 Elasticsearch 性能测试任务
    自从上次发布 esrally 教程已近两个月,期间不断有用户咨询使用过程中遇到的各种问题,尤其是由于测试数据托管在海外 AWS 上,导致下载速度极慢。为此,本文将详细介绍如何通过三个关键步骤高效执行 Elasticsearch 性能测试任务,帮助用户解决常见问题并提升测试效率。 ... [详细]
  • ElasticSearch版本:elasticsearch-7.3.0环境准备:curl-HContent-Type:applicationjso ... [详细]
author-avatar
那一年2502931247
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有