从lucene到ElasticSearch

初识 Lucene


1.什么是Lucene

  • Lucene 是一个基于 Java 的全文信息检索工具包,它不是一个完整的搜索应用程序,而是为你的应用程序提供索引和搜索功能。Lucene 目前是 Apache Jakarta 家族中的一个开源项目。也是目前最为流行的基于 Java 开源全文检索工具包。
  • 目前已经有很多应用程序的搜索功能是基于 Lucene 的,比如 Eclipse 的帮助系统的搜索功能。Lucene 能够为文本类型的数据建立索引,所以你只要能把你要索引的数据格式转化的文本的,Lucene 就能对你的文档进行索引和搜索。比如你要对一些 HTML 文档,PDF 文档进行索引的话你就首先需要把 HTML 文档和 PDF 文档转化成文本格式的,然后将转化后的内容交给 Lucene 进行索引,然后把创建好的索引文件保存到磁盘或者内存中,最后根据用户输入的查询条件在索引文件上进行查询。不指定要索引的文档的格式也使 Lucene 能够几乎适用于所有的搜索应用程序。

如图是应用程序与lucene之间的关系
在这里插入图片描述
使用过程大概如下:

  • 索引流程:即采集数据–>构建文档对象–>分析文档(分词)–>创建索引。
  • 搜索流程:即用户通过搜索界面–>创建查询–>执行搜索,搜索器从索引库搜索–>渲染搜索结果。

Lucene详细教程可看这里

2.小例子

这里用的scala,java一样,小demo如下

  • 创建索引
  /**
 * 创建索引
 * * @param dir
 * * @param file
 * * @throws Exception
   */
  @throws[IOException]
  def createIndex(dir: Directory,file:File): Unit = {
    // 1. 参数:1.创建 Directory (索引存放位置),这里是参数dir 2.需要建立的索引的目录
    // 2. 创建IndexWriter 写索引  StandardAnalyzer分析器,分词,英文空格,中文单个字即为一个词条
    val analyzer = new StandardAnalyzer
    val iwc = new IndexWriterConfig(analyzer)
    var indexWriter = new IndexWriter(dir, iwc)
    for (f <- file.listFiles) {      //获取目录下的所有文件
      // 3. 创建Documen,并 添加field
      var document = new Document()
      document.add(new Field("content", FileUtils.readFileToString(f, "utf-8"), TextField.TYPE_STORED))
      document.add(new TextField("fileName", f.getName, Field.Store.YES))
      document.add(new StringField("filePath", f.getAbsolutePath, Field.Store.YES))
      // 4. 通过IndexWriter 添加文档到索引中
      indexWriter.addDocument(document)
    }
    indexWriter.close
  }
  • 根据内容搜索
/**
 * 根据内容搜索
 * * @param dir
 * * @param searchWord
 * @throws Exception
   */
  @throws[Exception]
  def search(dir: Directory,searchWord:String): Unit = {
    // 1. 参数一:索引存储位置,参数二:需要搜索的词
    // 2. 创建 IndexReader  读取索引
    var indexReader = DirectoryReader.open(dir)
    // 3. 创建 IndexSearch
    val indexSearcher = new IndexSearcher(indexReader)
    // 4. 创建搜索的Query
    // 创建parse确定搜索的内容为content
    val queryParser = new QueryParser("content", new StandardAnalyzer)
    // 创建Query,表示搜索域中的内容
    val query = queryParser.parse(searchWord);
    //val query = new TermQuery(new Term("content", "xxxx"))  ----也可以这么写,query 为多个xxxQuery的父类
    // 5. 搜索并返回 TopDocs,这里是返回前5条结果
    val topDocs = indexSearcher.search(query, 5)
    // 6. 根据topDocs 获得 scoreDocs  按分数排序
    val totalHits: Int = topDocs.totalHits    //查到的数量
    println(totalHits)
    var document = new Document()
    for (doc <- topDocs.scoreDocs) { // 获取Document对象
      document = indexSearcher.doc(doc.doc)
      // 根据Document对象获取需要的值
      System.out.println(document.get("fileName"))
      System.out.println(document.get("content"))
    }
    indexReader.close
  }
  • 跑一下
  def main(args: Array[String]): Unit = {
    val file = new File("xxxxxxxxx")  //需要建立索引的目录
   // val dir = new RAMDirectory   //可以索引存在内存里
    val dir2 = FSDirectory.open(new File("xxxxxxxxxxxxxx").toPath)   //本地路径 存索引
    new lucene_1().createIndex(dir2,file)
    new lucene_1().search(dir2,"啊")
  //  new lucene_1().search(dir2,"啊 ada")
  //  new lucene_1().search(dir2,"啊 ada xxxx")
  }
  • 结果
2
test1.txt
啊啊啊
新建文本文档.txt
啊啊啊
ada
--------------------------------
3
新建文本文档.txt
啊啊啊
ada
test1.txt
啊啊啊
123231.txt
123
12313123123
ada
--------------------------------
4
新建文本文档.txt
啊啊啊
ada
abc.txt
xxxx
test1.txt
啊啊啊
123231.txt
123
12313123123
ada

ElasticSearch


1.介绍

Elasticsearch是一个基于Apache Lucene™的开源搜索引擎。无论在开源还是专有领域,Lucene可以被认为是迄今为止最先进、性能最好的、功能最全的搜索引擎库。

但是,Lucene只是一个库。想要使用它,你必须使用Java来作为开发语言并将其直接集成到你的应用中,更糟糕的是,Lucene非常复杂,你需要深入了解检索的相关知识来理解它是如何工作的。
Elasticsearch也使用Java开发并使用Lucene作为其核心来实现所有索引和搜索的功能,但是它的目的是通过简单的RESTful API来隐藏Lucene的复杂性,从而让全文搜索变得简单。

不过,Elasticsearch不仅仅是Lucene和全文搜索,我们还能这样去描述它:

  • 分布式的实时文件存储,每个字段都被索引并可被搜索
  • 分布式的实时分析搜索引擎
  • 可以扩展到上百台服务器,处理PB级结构化或非结构化数据

而且,所有的这些功能被集成到一个服务里面,你的应用可以通过简单的RESTful API、各种语言的客户端甚至命令行与之交互。
上手Elasticsearch非常容易。它提供了许多合理的缺省值,并对初学者隐藏了复杂的搜索引擎理论。它开箱即用(安装即可使用),只需很少的学习既可在生产环境中使用。
Elasticsearch在Apache 2 license下许可使用,可以免费下载、使用和修改。
随着你对Elasticsearch的理解加深,你可以根据不同的问题领域定制Elasticsearch的高级特性,这一切都是可配置的,并且配置非常灵活。

上述描述来源自—Elasticsearch 权威指南(中文版)
ElasticSearch中文社区

2.基本概念

  • 索引
  1. 一个 索引类似于传统关系数据库中的一个 数据库 ,是一个存储关系型文档的地方,是ES对逻辑数据的逻辑存储,索引的结构是为快速有效的全文检索做准备。 索引 (index) 的复数词为 indices 或 indexes 。
  2. 索引一个文档 就是存储一个文档到一个 索引 (名词)中以便它可以被检索和查询到。这非常类似于 SQL 语句中的 INSERT 关键词,除了文档已存在时新chaj文档会替换旧文档情况之外。
  3. 倒排索引源于实际应用中需要根据属性的值来查找记录。这种索引表中的每一项都包括一个属性值和具有该属性值的各记录的地址。由于不是由记录来确定属性值,而是由属性值来确定记录的位置,因而称为倒排索引(inverted index)。带有倒排索引的文件我们称为倒排索引文件,简称倒排文件(inverted file)。
  • 文档
  1. 存储在ES上的主要实体叫文档
  2. 在ES中,一个索引对象可以存储很多不同用途的对象(文档类型–废弃)
  3. 在应用程序中对象很少只是一个简单的键和值的列表。通常,它们拥有更复杂的数据结构,可能包括日期、地理信息、其他对象或者数组等。
  4. Elasticsearch 是 面向文档 的,意味着它存储整个对象或 文档。Elasticsearch 不仅存储文档,而且索引每个文档的内容使之可以被检索。在 Elasticsearch 中,你 对文档进行索引、检索、排序和过滤–而不是对行列数据。这是一种完全不同的思考数据的方式,也是 Elasticsearch 能支持复杂全文检索的原因。
  • 映射
  1. 存储有关字段的信息,每一个文档类型都有自己的映射。
  • 分片
  1. 索引可能存储大量可能超过单个节点的硬件限制的数据。例如,占用1TB磁盘空间的十亿个文档的单个索引可能不适合单个节点的磁盘,或者可能太慢而无法单独从单个节点提供搜索请求。为了解决这个问题,Elasticsearch 提供了将索引细分为多个称为分片的功能。创建索引时,只需定义所需的分片数即可。每个分片本身都是一个功能齐全且独立的“索引”,可以托管在集群中的任何节点上。
  2. 设置分片的目的及原因主要是:它允许您水平拆分/缩放内容量;它允许您跨分片(可能在多个节点上)分布和并行化操作,从而提高性能/吞吐量,分片的分布方式以及如何将其文档聚合回搜索请求的机制完全由 Elasticsearch 管理,对用户而言是透明的。
  3. 在可能随时发生故障的网络/云环境中,分片非常有用,建议使用故障转移机制,以防分片/节点以某种方式脱机或因任何原因消失。为此,Elasticsearch 允许您将索引的分片的一个或多个副本制作成所谓的副本分片或简称副本。
  • 副本
  1. 副本,是对分片的复制。目的是为了当分片/节点发生故障时提供高可用性,它允许您扩展搜索量/吞吐量,因为可以在所有副本上并行执行搜索。总而言之,每个索引可以拆分为多个分片。索引也可以复制为零次(表示没有副本)或更多次。复制之后,每个索引将具有主分片(从原始分片复制而来的)和复制分片(主分片的副本)。

3.小结

我们假设有一个集群由三个节点组成(Node1 , Node2 , Node3)。 它有两个主分片(P0 , P1),每个主分片有两个副本分片(R0 , R1)。相同分片的副本不会放在同一节点,所以我们的集群看起来如下图所示 “有三个节点和一个索引的集群”。
在这里插入图片描述
类似于关系型数据库:数据库集群,假如有个用户表,我担心数据量过大,我新建了多个用户表(即 Shard),将用户信息数据切分成多份,然后根据某种规则分到这些用户表中,我又担心某个表会出现异常造成数据丢失,我又将每个表分别备份了一次(即 Replica )。

  • 副本是乘法,越多越浪费,但也越保险。分片是除法,分片越多,单分片数据就越少也越分散。

我们可以类比传统关系型数据库:

  • 关系型数据库 -> Databases(库) -> Tables(表) -> Rows(行) -> Columns(列)。
  • Elasticsearch -> Indeces(索引) -> Types(类型) -> Documents(文档) -> Fields(属性)。

Elasticsearch集群可以包含多个索引(indices)(数据库),每一个索引可以包含多个类型 (Types)(表),每一个类型包含多个文档(documents)(行),然后每个文档包含多个字段(Fields)(列)。

4.安装使用

这里选用es-5.5.1
步骤如下

  • 第一步:首先获取安装包,解压

wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-5.5.1.zip
unzip elasticsearch-5.5.1.zip

  • 第二步:改配置文件,并发送到其他两台机器(对应的地方需要修改)
cluster.name: esCluster
node.name: host1
node.master: true
node.data: true
path.data: /usr/local/include/elasticsearch-5.5.1/data
path.logs: /usr/local/include/elasticsearch-5.5.1/logs
network.host: host1
http.port: 9200
transport.tcp.port: 9300
discovery.zen.ping.unicast.hosts: ["host1:9300","host2:9300","host3:9300"]
discovery.zen.minimum_master_nodes: 2
  • 第三步:新建用户、用户组 (在 Linux 环境中,elasticsearch 不允许以 root 权限来运行!所以需要创建一个非root用户,以非root用户来起es) 三台机器

groupadd esgroup
useradd esuser -g esgroup -p 112233

  • 第四步:更改几个限制,三台机器

vim /etc/security/limits.conf
#* soft nofile 65535 #主要有星号 ,重启生效
#* hard nofile 65537
echo “vm.max_map_count=262144” > /etc/sysctl.conf
sysctl -p

上面这个限制是为了避免这两个问题
在这里插入图片描述在这里插入图片描述

  • 第五步:启动es,三台机器

chown -R esuser elasticsearch-5.5.1
su esuser
bin/elasticsearch -d

  • 第六步:检查是否成功启动

curl host1:9200

这里是引用

5.es的web前端插件elasticsearch-head安装

  • 第一步,把需要的东西安装好,该插件在es5版本以后采用独立服务的形式进行安装使用(之前的版本可以直接在es安装目录中plugin安装)

yum -y install epel-release (可以yum info epel-release查看是否已经安装)
yum -y install nodejs
yum -y install git

  • 第二步,git拉取

git clone https://github.com/mobz/elasticsearch-head.git

  • 第三步,安装依赖(插件安装相对会慢一些,请耐心等待…)

cd elasticsearch-head/
npm install --registry=https://registry.npm.taobao.org #安装依赖 指定淘宝的npm源加速

  • 第四步,修改配置

vim /etc/elasticsearch/elasticsearch.yml
加入:
http.cors.enabled: true
http.cors.allow-origin: “*”


修改Gruntfile.js文件,新增hostname: ‘*’(图中红圈中为新增)
在这里插入图片描述
修改head/_site/app.js,修改head连接es的地址,本来是localhost(文件内可以通过‘?localhost’寻找位置)
在这里插入图片描述

  • 第五步,启动

nohup bin/grunt server &
浏览器访问ip:9100(或者你配置的其他port)
红圈处填你配置的es ip:port在这里插入图片描述

6.es的简单使用

  • 创建/更新

PUT/POST
例子:
创建索引:curl -XPUT ‘host1:9200/test1’ -d ‘{“settings”:{“number_of_shards”:10,“number_of_replicas”:1}}’
在这里插入图片描述
在这里插入图片描述
新增document:curl -XPUT “host1:9200/test1/testtype/1” -H ‘Content-Type:application/json’ -d ‘{“first_name”:“yyy”,“age”:20,“about”:“hello world!”}’
-d 指定要传输的数据
-H 指定http请求头信息 在这里插入图片描述
在这里插入图片描述
curl -XPOST “host1:9200/test1/testtype” -H ‘Content-Type:application/json’ -d ‘{“first_name”:“yangy”,“age”:18,“about”:“hello es!”}’
未指定id,会随机创建id在这里插入图片描述
更新数据:curl -XPOST http://host1:9200/test1/testtype/1/_update -d ‘{“doc”:{“first_name”: “yyynb”, “age”: “21”}}’
在这里插入图片描述
在这里插入图片描述
POST与PUT的区别:
1.更新:PUT会将新的json值完全替换掉旧的;而POST方式只会更新相同字段的值,其他数据不会改变,新提交的字段若不存在则增加。
2.PUT和DELETE操作是幂等的。所谓幂等是指不管进行多少次操作,结果都一样。比如用PUT修改一篇文章,然后在做同样的操作,每次操作后的结果并没有什么不同,DELETE也是一样。
3.POST操作不是幂等的,比如常见的POST重复加载问题:当我们多次发出同样的POST请求后,其结果是创建了若干的资源。
4.创建操作可以使用POST,也可以使用PUT,区别就在于POST是作用在一个集合资源(/articles)之上的,而PUT操作是作用在一个具体资源之上的(/articles/123)。

  • 删除

DELETE
删除索引: curl -XDELETE ‘host1:9200/test1’
按id删除:DELETE /索引库名/类型名/id值
按查询删除:POST /索引库名/类型名/_delete_by_query

  • 查询

GET
查询整个索引库:curl -XGET http://host:9200/test/_search?pretty
在url后面加上一个pretty则会对返回结果进行格式化,
查询某一个type:curl -XGET http://host:9200/test/testtype/_search?pretty
查询具体的一条记录:curl -XGET http://host:9200/test/testtype/1?pretty
查询一条索引文档中的具体的字段:curl -XGET http://host:9200/test/testtype/1?_source=name&pretty
如果要查询多个字段,使用","进行隔开。eg.
curl -XGET http://host:9200/test/testtype/1?_source=name,author&pretty
获取source所有数据
curl -XGET http://host:9200/test/testtype/1?_source&pretty
根据条件进行查询
curl -XGET http://host:9200/test/testtype/_search?q=age:20

  • 批处理

先新建一个文件,在文件里写下需要批处理的操作:
如这种
{“index”:{"_index":“test”,"_type":“testtype”,"_id":“1”}}
{“first_name”:“st01”,“age”:“15”,“about”:“st01”}
{“create”:{"_index":“test”,"_type":“testtype”,"_id":“2”}}
{“first_name”:“tea01”,“age”:“16”,“about”:“tea01”}
curl -XPUThttp://192.168.79.131:9200/_bulk --data-binary @/usr/local/request1
–data-binary@之间有空格隔开

  • 当然操作还有很多,而且不仅可以这样操作也可以从elasticsearch-head进行操作,方法都跟上面写的类似,剩下的大家自己摸索一下,尝试会加快学习的速度哦。

到这里结束啦!

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值