文章目录
  1. 1. 全文检索
    1. 1.1. 为什么使用全文检索
      1. 1.1.1. 说明
      2. 1.1.2. 有数据库为什么要solr
        1. 1.1.2.1.
    2. 1.2. 全文检索定义
      1. 1.2.1. 数据分类
      2. 1.2.2. 非结构化数据查询方法
        1. 1.2.2.1. 顺序扫描法(Serial Scanning)
        2. 1.2.2.2. 全文检索(Full-text Search)
      3. 1.2.3. 如何实现全文检索
      4. 1.2.4. 全文检索技术的应用场景
      5. 1.2.5. 总结
        1. 1.2.5.1. 索引
        2. 1.2.5.2. 搜索
    3. 1.3. 全文检索实现
      1. 1.3.1. 创建索引
      2. 1.3.2. 获得原始文档
      3. 1.3.3. 创建文档对象
      4. 1.3.4. 分析文档
      5. 1.3.5. 创建索引
      6. 1.3.6. 查询索引
      7. 1.3.7. 用户查询接口
      8. 1.3.8. 创建查询
      9. 1.3.9. 执行查询
      10. 1.3.10. 渲染结果
    4. 1.4. Solr集群配置的一些说明

全文检索

为什么使用全文检索

说明

​ 没有使用全文检索的时候,大部分会利用WHERE子句匹配LIKE关键词,在庞大的数据字段中搜索某些想要的字,如: select * from test WHERE Notes LIKE ‘%你好%’

​ 然而这种查询方式非常没有效率,即使在Notes字段建立了一般的索引,帮助也不大,因为SQL SERVER为数据表建立的索引是排序过的数据结构。因此,可以用二分搜索算法来快速寻找数据,但搜索’%你好%’可没有什么顺序可言,因为搜索条件以’%’开头.
全文检索则提供完全不同的索引架构,以关键词为基础建立全文检索索引。搭配特有的SQL查询语法,对于大型文本的字词查询更具弹性和效率

例1:

1
2
3
4
5
6
我们有一个表大概有50万条数据,其中有一个字段是字符串类型需要实现like 模糊查询,我们使用的是mysql,虽然已经建立了索引,但是由于使用的是%a%模式匹配,很不给力,在大量并发下,数据库会挂掉,或者用户等到抓狂查询结果还不出来,后来想出了一个办法解决了这个问题,每次查询可以控制在15ms左右,效果很是不错。我们采用是全文索引技术:
1、使用lucene或者其他可以提供全文索引的nosql数据库,比如tt server或mongodb
2、把需要模糊查询的字段的字符串数据进行”全分词“,即把所有可能分词都枚举出来,比如abc,可以分成a,ab,abc,b,bc,c
3、把这些分好的term建立索引,如果使用lucene则需要建立一个分词器,能把传入的字符串分解成第2步描述的分词后建立索引,如果使用的是mongodb,则把分好的词存入一个字段并且建立索引,如果使用的tt server,那就简单了,直接建立qgram类型的索引即可,不需要自己去分词,我们最终就是使用tt server解决的问题
4、使用各自提供的查询语法进行查询,绝对高效
最终采用tt server的qgram方式实现,50多万条数据的模糊查询时间不超过15毫秒,有缓存的情况可能是0ms。

例2:mysql的全文索引与like实现

1
2
3
4
5
6
7
8
在数据库使用中,DBA都会告诉大家SQL的LIKE条件为%XXX%号时,由于不能使用索引,当数据量变大时(比如超过百万条),全表扫描会导致性能很差。
  但是在实际业务中,很难避免MySQL全文检索并Like索引的这种需求。比如模糊搜索用户帐号,昵称之类。既然这个需求必须做,但又不可以直接用LIKE。这里我和大家分享一下我们关于这种需求的一种解决方案。当然别人也可能采用过类似的办法,我不是很清楚。所以也用一下“原创”吧。

  MySQL数据库很早就支持全文索引,但是全文索引和LIKE语句是不同的。具体点说,全文索引的单位是词,耳LIKE匹配的是字符。当然实际的区别更大,比如“老鼠爱大米”这段文本用全文搜索的话,条件“老鼠爱大米”,“老鼠和大米”,“大米老鼠”,“大米与老鼠”会搜索到内容,但是“爱”,“鼠爱”,“爱大”不会搜索到内容。反之,使用LIKE搜索时,“老鼠和大米”,“大米老鼠”,“大米与老鼠”不会找到内容,而“爱”,“鼠爱”,“爱大”会找到内容。我们这里不讨论两种方式的优劣,根据实际情况每种功能都会有各自的实际需求。比如对于大段文本,全文检索是最好的方法,但是对于姓名,帐号,昵称等很短的通常无意义文本,LIKE会更合适一些。
  虽然全文检索和LIKE搜索不同,但是在特殊情况下,可以用全文搜索功能来实现LIKE搜索。具体就是每个字符作为一个词,而且使用双引号来限制词精确匹配(简单点说就是老鼠大米和大米老鼠不同),这样可以实现LIKE搜索的功能。
  

来自:https://www.cnblogs.com/bobsoft/archive/2012/10/07/2714545.html

例3:

1
2
3
4
5
6
当我们访问购物网站的时候,我们可以根据我们随意所想的内容输入关键字就可以查询出相关的内容,这是怎么做到呢?这些随意的数据不可能是根据数据库的字段查询的,那是怎么查询出来的呢,为什么千奇百怪的关键字都可以查询出来呢?
答案就是全文检索工具的实现,luncence采用了词元匹配和切分词。举个例子:北京天安门----luncence切分词:北京  京天  天安  安门  等等这些分词。所以我们搜索的时候都可以检索到。
有一种分词器就是IKanalyzer中文分词器,它有细粒度切分和智能切分,即根据某种智能算法。
这就使用solr的最大的好处:检索功能的实现。

来自:https://blog.csdn.net/jokeylin/article/details/80562148

有数据库为什么要solr

​ lucene负责数据存储,而solr只是一个引擎提供搜索和插入而已,跟数据库的解释器一样,有什么好处呢,比如一个数据库有一个字段存了1000个字,你想从这些字里面搜一个词的时候,普通的数据库只会让你使用like去查询,他会遍历每个字去模糊匹配,效率很低,而且有些是无法查询的,当然除了像一些特殊的数据库带有分词,比如postgresql,那lucene做的事情就是分词,然后去匹配分词的词中是否有你想搜的词就好了,当然了,为了提高这种检索效率和内存节省底层做了很复杂的事情,可以这么简单的认为,全文搜索这件事情上数据库是无法满足的

​ 大型的SQL数据库上很难执行高速的查询。Solr是Apache 下的一个开源项目,使用Java基于Lucene开发的全文检索服务;它是一个独立的企业级搜索应用服务器,它对外提供类似于Web-service的API接口。用户可以通过http请求,向搜索引擎服务器提交一定格式的XML文件,生成索引;也可以通过Http Get操作提出查找请求,并得到XML格式的返回结果。

​ 为什么使用solr???????

 第一点原因来自SQL数据库在性能上缺乏亮点。基本上,你需要在你的查询中使用JOIN操作。

 第二点原因是文档的天然数据特性:松散的文本文件,这种查询都是需要使用LIKE。然而joins和likes都是性能杀手,在目前的数据库引擎中是不方便的。

所以,很多时候希望找到一种跟SQL完全不同的数据检索方式:倒排索引。

这种数据结构类似与美化过的词典:

      key是单个的term

      values是跟term对应的文档列表

这种数据方式可以帮助在大型的数据库上面进行高速查询。

全文检索定义

数据分类

我们生活中的数据总体分为两种:结构化数据和非结构化数据。

  • 结构化数据:指具有固定格式或有限长度的数据,如数据库中的数据,元数据等。
  • 非结构化数据:指不定长或无固定格式的数据,如邮件,word文档等磁盘上的文件。

非结构化数据查询方法

顺序扫描法(Serial Scanning)

​ 所谓顺序扫描,比如要找内容包含某一个字符串的文件,就是一个文档一个文档的看,对于每一个文档,从头看到尾,如果此文档包含此字符串,则此文档为我们要找的文件,接着看下一个文件,直到扫描完所有的文件。如利用windows的搜索也可以搜索文件内容,只是相当的慢。

​ 将非结构化数据中的一部分信息提取出来,重新组织,使其变得有一定结构,然后对此有一定结构的数据进行搜索,从而达到搜索相对较快的目的。这部分从非结构化数据中提取出的然后重新组织的信息,我们称之索引。
例如:字典。字典的拼音表和部首检字表就相当于字典的索引,对每一个字的解释是非结构化的,如果字典没有音节表和部首检字表,在茫茫辞海中找一个字只能顺序扫描。然而字的某些信息可以提取出来进行结构化处理,比如读音,就比较结构化,分声母和韵母,分别只有几种可以一一列举,于是将读音拿出来按一定的顺序排列,每一项读音都指向此字的详细解释的页数。我们搜索时按结构化的拼音搜到读音,然后按其指向的页数,便可找到我们的非结构化数据——也即对字的解释。
这种先建立索引,再对索引进行搜索的过程就叫全文检索(Full-text Search)。
虽然创建索引的过程也是非常耗时的,但是索引一旦创建就可以多次使用,全文检索主要处理的是查询,所以耗时间创建索引是值得的。

如何实现全文检索

可以使用Lucene实现全文检索。Lucene是apache下的一个开放源代码的全文检索引擎工具包(提供了Jar包,实现全文检索的类库)。它提供了完整的查询引擎和索引引擎,部分文本分析引擎。Lucene的目的是为软件开发人员提供一个简单易用的工具包,以方便地在目标系统中实现全文检索的功能。
注意:Lucene只是一个引擎,只是一个工具包,如果使用Lucene开发全文检索功能,要记住Lucene是不能单独运行的。

全文检索技术的应用场景

对于数据量大、数据结构不固定的数据可采用全文检索方式搜索。例如:

使用全文检索技术可以实现搜索引擎(百度、google…),搜索引擎可以搜索互联网上所有的内容(网页、pdf电子书、视频、音乐)。
Lucene和搜索引擎的区别:搜索引擎是对外提供全文检索服务,是可以单独运行的。Lucene只是一个工具包不能单独运行,需要在project中加入lucene的jar包,最终project在JVM中运行。
使用全文检索技术可以实现站内搜索,站内搜索只能搜索本网站的信息(网页、pdf电子书、视频、音乐、关系数据库中的信息等等),比如:电商网站搜索商品信息,论坛网站搜索网内帖子。

总结

全文检索过程分为索引、搜索两个过程:

索引

从关系数据库中、互联网上、文件系统采集源数据(要搜索的目标信息),源数据的来源是很广泛的。
将源数据采集到一个统一的地方,要创建索引,将索引创建到一个索引库(文件系统)中,从源数据库中提取关键信息,从关键信息中抽取一个一个词,词和源数据是有关联的。也即创建索引时,词和源数据有关联,索引库中记录了这个关联,如果找到了词就说明找到了源数据(http的网页、pdf电子书等……)。

搜索

用户执行搜索(全文检索)编写查询关键字。
从索引库中搜索索引,根据查询关键字搜索索引库中的一个一个词。
展示搜索的结果。

全文检索实现

创建索引

​ 对文档索引的过程,将用户要搜索的文档内容进行索引,索引存储在索引库(index)中。
这里我们要搜索的文档是磁盘上的文本文件,根据案例描述:凡是文件名或文件内容包括关键字的文件都要找出来,这里要对文件名和文件内容创建索引。

获得原始文档

​ 原始文档是指要索引和搜索的内容。原始内容包括互联网上的网页、数据库中的数据、磁盘上的文件等

​ 从互联网上、数据库、文件系统中等数据源处获取需要搜索的原始信息,这个过程就是信息采集,信息采集的目的是为了对原始内容进行索引。针对不同的源数据,使用不同的技术进行采集获得原始文档:

针对互联网上的数据,使用http协议抓取html网页到本地,生成一个html文件。
针对关系数据库中的数据,连接数据库读取表中的数据。
针对文件系统中的数据,通过流读取文件系统的文件。

以上技术中使用第一种较多,因为目前全文检索主要搜索数据的来源是互联网,在Internet上采集信息的软件通常称为爬虫或蜘蛛,也称为网络机器人,爬虫访问互联网上的每一个网页,将获取到的网页内容存储起来,所以搜索引擎使用一种爬虫程序抓取网页( 通过http抓取html网页信息)。
Lucene不提供信息采集的类库,需要自己编写一个爬虫程序实现信息采集,也可以通过一些开源软件实现信息采集,以下是一些爬虫项目(了解):

1
2
3
4
Solr(http://lucene.apache.org/solr),solr是apache的一个子项目,支持从关系数据库、xml文档中提取原始数据。
Nutch(http://lucene.apache.org/nutch), Nutch是apache的一个子项目,包括大规模爬虫工具,能够抓取和分辨web网站数据。
jsoup(http://jsoup.org/ ),jsoup是一款Java的HTML解析器,可直接解析某个URL地址、HTML文本内容。它提供了一套非常省力的API,可通过DOM,CSS以及类似于jQuery的操作方法来取出和操作数据。
Heritrix(http://sourceforge.net/projects/archive-crawler/files/),Heritrix是一个由java开发的、开源的网络爬虫,用户可以使用它来从网上抓取想要的资源。其最出色之处在于它良好的可扩展性,方便用户实现自己的抓取逻辑。

创建文档对象

分析文档

创建索引

查询索引

用户查询接口

创建查询

执行查询

渲染结果

Solr集群配置的一些说明

​ 1)安装zookeeper集群,做配置管理

​ 2)安装四个tomcat,和四个索引库,依旧是一对一(solr的web服务中web.xml配置索引库的绝对路径)

​ 3)上传索引库的配置文件至zookeeper(索引库目录下的collection/conf)

​ 4)修改每一个索引库下的 solr.xml,指定当前实例运行的ip地址及端口号

​ 5)修改每一台solr的tomcat的bin目录下 catalina.sh文件中加入DzkHost指定zookeeper服务器地址

​ JAVA_OPTS=”-DzkHost=192.168.70.147:2181,192.168.70.147:2182,192.168.70.14 7:2183”

注意:加入JAVA_OPTS的参数的含义,也就是程序可以读取该键值对配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
JVM自定义参数通过java命令的可选项:
-D<name>=<value>
来传入JVM,传入的参数作为system的property。因此在程序中可以通过下面的语句获取参数值:
System.getProperty(<name>)

public class JVMParameter {

/**
* 运行前设置JVM参数 -Djvm.index=1
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
String jvmIndex = System.getProperty("jvm.index");
System.out.println("jvmIndex=" + jvmIndex);
}
}
运行class命令:
java -Djvm.index=1 JVMParameter

说明:
JVM自定义参数可用来在集群环境区分当前class运行在哪个JVM上,可以达到让某个class只在某个指定的JVM上运行,避免多个JVM同时运行,出现混乱。也可以作为程序读取的配置信息

参考:

https://blog.csdn.net/qq_16162981/article/details/70142166

https://blog.csdn.net/yerenyuan_pku/article/details/72582979

文章目录
  1. 1. 全文检索
    1. 1.1. 为什么使用全文检索
      1. 1.1.1. 说明
      2. 1.1.2. 有数据库为什么要solr
        1. 1.1.2.1.
    2. 1.2. 全文检索定义
      1. 1.2.1. 数据分类
      2. 1.2.2. 非结构化数据查询方法
        1. 1.2.2.1. 顺序扫描法(Serial Scanning)
        2. 1.2.2.2. 全文检索(Full-text Search)
      3. 1.2.3. 如何实现全文检索
      4. 1.2.4. 全文检索技术的应用场景
      5. 1.2.5. 总结
        1. 1.2.5.1. 索引
        2. 1.2.5.2. 搜索
    3. 1.3. 全文检索实现
      1. 1.3.1. 创建索引
      2. 1.3.2. 获得原始文档
      3. 1.3.3. 创建文档对象
      4. 1.3.4. 分析文档
      5. 1.3.5. 创建索引
      6. 1.3.6. 查询索引
      7. 1.3.7. 用户查询接口
      8. 1.3.8. 创建查询
      9. 1.3.9. 执行查询
      10. 1.3.10. 渲染结果
    4. 1.4. Solr集群配置的一些说明