热门标签 | 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


推荐阅读
  • 这个问题困扰了我两天,卸载Dr.COM客户端(我们学校上网要装这个客户端登陆服务器,以后只能在网页里输入用户名和密码了),问题解决了。问题的现象:在实验室机台式机上安装openfire和sp ... [详细]
  • 本文介绍了如何使用PHP向系统日历中添加事件的方法,通过使用PHP技术可以实现自动添加事件的功能,从而实现全局通知系统和迅速记录工具的自动化。同时还提到了系统exchange自带的日历具有同步感的特点,以及使用web技术实现自动添加事件的优势。 ... [详细]
  • 本文介绍了使用postman进行接口测试的方法,以测试用户管理模块为例。首先需要下载并安装postman,然后创建基本的请求并填写用户名密码进行登录测试。接下来可以进行用户查询和新增的测试。在新增时,可以进行异常测试,包括用户名超长和输入特殊字符的情况。通过测试发现后台没有对参数长度和特殊字符进行检查和过滤。 ... [详细]
  • 如何用UE4制作2D游戏文档——计算篇
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了如何用UE4制作2D游戏文档——计算篇相关的知识,希望对你有一定的参考价值。 ... [详细]
  • Voicewo在线语音识别转换jQuery插件的特点和示例
    本文介绍了一款名为Voicewo的在线语音识别转换jQuery插件,该插件具有快速、架构、风格、扩展和兼容等特点,适合在互联网应用中使用。同时还提供了一个快速示例供开发人员参考。 ... [详细]
  • 本文介绍了Web学习历程记录中关于Tomcat的基本概念和配置。首先解释了Web静态Web资源和动态Web资源的概念,以及C/S架构和B/S架构的区别。然后介绍了常见的Web服务器,包括Weblogic、WebSphere和Tomcat。接着详细讲解了Tomcat的虚拟主机、web应用和虚拟路径映射的概念和配置过程。最后简要介绍了http协议的作用。本文内容详实,适合初学者了解Tomcat的基础知识。 ... [详细]
  • 本文介绍了在使用Python中的aiohttp模块模拟服务器时出现的连接失败问题,并提供了相应的解决方法。文章中详细说明了出错的代码以及相关的软件版本和环境信息,同时也提到了相关的警告信息和函数的替代方案。通过阅读本文,读者可以了解到如何解决Python连接服务器失败的问题,并对aiohttp模块有更深入的了解。 ... [详细]
  • 大数据Hadoop生态(20)MapReduce框架原理OutputFormat的开发笔记
    本文介绍了大数据Hadoop生态(20)MapReduce框架原理OutputFormat的开发笔记,包括outputFormat接口实现类、自定义outputFormat步骤和案例。案例中将包含nty的日志输出到nty.log文件,其他日志输出到other.log文件。同时提供了一些相关网址供参考。 ... [详细]
  • 本文介绍了在sqoop1.4.*版本中,如何实现自定义分隔符的方法及步骤。通过修改sqoop生成的java文件,并重新编译,可以满足实际开发中对分隔符的需求。具体步骤包括修改java文件中的一行代码,重新编译所需的hadoop包等。详细步骤和编译方法在本文中都有详细说明。 ... [详细]
  • Maven构建Hadoop,
    Maven构建Hadoop工程阅读目录序Maven安装构建示例下载系列索引 序  上一篇,我们编写了第一个MapReduce,并且成功的运行了Job,Hadoop1.x是通过ant ... [详细]
  • 什么是大数据lambda架构
    一、什么是Lambda架构Lambda架构由Storm的作者[NathanMarz]提出,根据维基百科的定义,Lambda架构的设计是为了在处理大规模数 ... [详细]
  • Hadoop源码解析1Hadoop工程包架构解析
    1 Hadoop中各工程包依赖简述   Google的核心竞争技术是它的计算平台。Google的大牛们用了下面5篇文章,介绍了它们的计算设施。   GoogleCluster:ht ... [详细]
  • Java序列化对象传给PHP的方法及原理解析
    本文介绍了Java序列化对象传给PHP的方法及原理,包括Java对象传递的方式、序列化的方式、PHP中的序列化用法介绍、Java是否能反序列化PHP的数据、Java序列化的原理以及解决Java序列化中的问题。同时还解释了序列化的概念和作用,以及代码执行序列化所需要的权限。最后指出,序列化会将对象实例的所有字段都进行序列化,使得数据能够被表示为实例的序列化数据,但只有能够解释该格式的代码才能够确定数据的内容。 ... [详细]
  • 【MEGA DEAL】Ruby on Rails编码训练营(97%折扣)限时特惠!
    本文介绍了JCG Deals商店提供的Ruby on Rails编码训练营的超值优惠活动,现在只需29美元即可获得,原价为$1,296。Ruby on Rails是一种用于Web开发的编程语言,即使没有编程或网页设计经验,也能在几分钟内构建专业的网站。该训练营共有6门课程,包括使用Ruby on Rails进行BDD的课程,使用RSpec 3和Capybara等。限时特惠,机会难得,赶快行动吧! ... [详细]
  • 一次上线事故,30岁+的程序员踩坑经验之谈
    本文主要介绍了一位30岁+的程序员在一次上线事故中踩坑的经验之谈。文章提到了在双十一活动期间,作为一个在线医疗项目,他们进行了优惠折扣活动的升级改造。然而,在上线前的最后一天,由于大量数据请求,导致部分接口出现问题。作者通过部署两台opentsdb来解决问题,但读数据的opentsdb仍然经常假死。作者只能查询最近24小时的数据。这次事故给他带来了很多教训和经验。 ... [详细]
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社区 版权所有