<title>title

华夏棋牌

<title>title

应用sphinx search打造你自己的中文搜索引擎

华夏棋牌Google搜索引擎培植至今曾经快20年了,以后全球种种年夜年夜小小类似的搜索引擎也陆续泛起、殒命。国际现在以百度为年夜,搜狗、360、必应等也势在必争。搜索引擎手艺也生长的相算作熟,同时也就泛起了许多开源的搜索引擎系统。好比,Solr、Lucene、Elasticsearch、Sphinx等。

本文以sphinx search为例来简介若何打造自己的搜索引擎。该搜索引擎的架构年夜致以下:

华夏棋牌Sphinx search

Sphinx search 是俄罗斯人用C++写的,速率很快,可以异常容易的与SQL数据库和剧本语言集成,内置MySQL和PostgreSQL 数据库数据源的支持。其官方网站是: http://sphinxsearch.com/

华夏棋牌可以说Sphinx支持网罗英文、中文等一切语言的搜索。英文是以空格、标点符号来朋分单词的,很容易切分。而中文词汇之间是没有空格的,很难分辨,以是才有了自然语言处置赏罚赏罚中的“中文分词”手艺的研究。Sphinx默许把中文按字拆分的,但这样就会发生搜索出不相关的内容来。好比,搜索“中国”,它会把同时网罗“中”和“国”但不网罗“中国”的文档搜出来。是以,有人就给Sphinx打了中文分词的补丁。

华夏棋牌假定没有弄错的话,最早添加中文分词的是Coreseek,似乎也是中文圈用得最广的支持中文分词的Sphinx,其它尚有sphinx-for-chinese。可是这二者基于的Sphinx版本都太低了,有许多若干许多几何年没有更新。其中存在的一些Sphinx的bug也没有处置赏罚赏罚。

github上有一个基于Sphinx 2.2.9版本的代码库添加了中文分词: https://github.com/eric1688/sphinx  经测试,该版本稳固性和速率都要好过coreseek。虽然它依然支持英文等其它语言的搜索,只是对中文搜索加倍准确了。

Sphinx 装配

git clone https://github.com/eric1688/sphinx
cd sphinx#编译(假定装配到/usr/local/sphinx目录,下文同) ./configure --prefix=/usr/local/sphinx# 诠释: --prefix 指定装配蹊径 --with-mysql 编译mysql支持 --with-pgsql 编译pgsql支持make
sudo make install

装配好后,在/usr/local/sphinx目录下有以下几个子目录:
etc/  sphinx装备文件,不合的索引可以写不合的装备文件
bin/  sphinx法式模范模范,其中有培植索引的法式模范模范:indexer, 搜索守护历程:searchd
var/  浅易用了放置indexer索引好的文件

华夏棋牌Sphinx索引的培植

MySQL数据库表结构 
华夏棋牌从下面的架构图可以看出来,我们要搜索的数据都存放在MySQL数据库中。假定我们的数据库称谓唤blog_data,其中有个表叫article,表结构以下:

字段名

诠释

华夏棋牌id    文章唯一id(主键)    

title    文章效果    

content    文章内容    

created_time    文章培植时间    

该article表可以是你自己网站的文本内容存放的表格,也能够或许是你的群集爬虫抓取到的数据存储表。

尚有培植另外一个表sph_counter用来存储indexer曾经索引的最年夜doc id

字段名

诠释

华夏棋牌counter_id    标志是对哪个表做纪录    

华夏棋牌max_doc_id    被索引表的最年夜ID    

note    注释,可以是表名    

华夏棋牌update_at    更新时间    

培植索引装备文件:  
新建或修改/usr/local/sphinx/etc/blog.conf 装备文件:

source blog_main
{
   type          = mysql
   sql_host      = localhost
   sql_user      = reader
   sql_pass      = readerpassword
   sql_db        = blog_data
   sql_port      = 3306
   sql_query_pre = SET NAMES utf8mb4
   sql_query_pre = REPLACE INTO sph_counter SELECT 1, MAX(id), 'article', NOW() FROM article

   sql_query     = SELECT id, title, content,  \
                   UNIX_TIMESTAMP(created_time) AS ctime, \
                   FROM article \
                   WHERE id <= (SELECT max_doc_id from sph_counter WHERE counter_id=1)
   sql_attr_timestamp = ctime  #从SQL读取到的值必须为整数,作为时间属性

}index blog_main{
   source       = blog_main #对应的source称谓
   path         = /user/local/sphinx/var/data/blog_main
   docinfo      = extern
   mlock        = 0
   morphology   = none
   min_word_len = 1
   html_strip   = 0

   charset_type     = utf-8
   chinese_dictionary = /user/local/sphinx/etc/xdict  #中文分词的词典
   ngram_len = 0
   stopwords        = /user/local/sphinx/etc/stop_words.utf8}

#全局index界说indexer{
   mem_limit = 512M}

#searchd服务界说searchd{
   listen          = 9900
   listen          = 9306:mysql41  # 实时索引监听的端口
   read_timeout    = 5
   max_children    = 90
   max_matches     = 100000
   max_packet_size = 32M
   read_buffer     = 1M
   subtree_docs_cache = 8M
   subtree_hits_cache = 16M
   #workers        = threads•
   dist_threads    = 2
   seamless_rotate = 0
   preopen_indexes = 0
   unlink_old      = 1
   pid_file  = /usr/local/sphinx/var/log/blog_searchd_mysql.pid
   log       = /usr/local/sphinx/var/log/blog_searchd_mysql.log
   query_log = /usr/local/sphinx/var/log/blog_query_mysql.log}

编辑好以上装备文件,便可以泉源培植索引了:

cd /usr/local/sphinx/bin
./indexer -c ../etc/blog.conf# 假定曾经有searchd在运转了,就要加 --roate 来阻拦索引

索引培植后,就会在var/data/下面有称谓前缀为blog_main.XXX的索引文件天生。

培植实时索引 
华夏棋牌下面的装备文件是培植一个静态索引,把其时数据库外面的所有数据阻拦索引。然则,你的数据库经常是赓续增添新数据的。为了实时索引并搜索到最新加入的数据,就须要装备实时索引了。

index rt_weixin                                                                                                     {
   type = rt
   path = /usr/local/sphinx/var/data/rt_blog
   rt_field = title
   rt_field = content

   rt_attr_timestamp = pubtime
   ngram_chars = U+3000..U+2FA1F #为了支持中文
   ngram_len = 1}

该客栈代码的作者能够是忘了给实时索引加中文分词,假定不装备ngram_chars 参数就不克不及搜到中文,添加后搜索是按单字婚配的,可见作者确切是忘了给实时索引部门加中文分词。

华夏棋牌添加以上实时索引后着实不克不及搜索到实时数据。实时索引的更新/添加只能经由历程SphinxQL(一个类似MySQL的协定),以是还要写一个Python剧本,从数据库读取最新的数据并经由历程SphinxQL更新到实时索引。

import MySQLdb# 毗连实时索引db_rt = MySQLdb.connect(
   '127.0.0.1',
   'nodb',  # 关于实时索引来讲,db,user,password都是不须要的,随便写。
   'noname',
   'nopass',
   port=9306,  # 实时索引监听的端口)  # 向实时索引更新数据的函数def into_rt(index_name, item):
   cursor = db_rt.cursor()
   fields = item.keys()
   values = item.values()
   fieldstr = ','.join(fields)
   valstr = ','.join(["'%s'"] * len(item))
   for i in xrange(len(values)):
       if isinstance(values[i], unicode):
           values[i] = values[i].encode('utf8')
       elif isinstance(values[i], datetime):
           try:
               values[i] = int(time.mktime(values[i].timetuple()))
           except:
               traceback.print_exc()
               print values[i]
               values[i] = int(time.time())
   sql = 'INSERT INTO %s (%s) VALUES(%s)' % (index_name, fieldstr, valstr)
   # print sql
   sql = sql % tuple(values)
   try:
       cursor.execute(sql)
       db_rt.commit()
   except Exception, e:
       if e[0] == 1064:
           # ignore duplicated id error
           pass
       else:
           traceback.print_exc()
           raise 'realtime index error'
   finally:
       cursor.close()

以上是实时培植实时索引的python法式模范模范的主要部门。可以把它设置成后台一直运转的守护法式模范模范,也能够或许在crontab外面装备每隔几分钟运转一次。

索引的更新 
静态的主索引假定只培植一次,实时索引的数据量会越积越多,对实时索引的搜索带来很年夜压力,以是我们要准时重新培植主索引,整理实时索引。
整理实时索引的法式模范模范可以参考下面培植实时索引的python法式模范模范。

华夏棋牌crontab 设置天天破晓1点运转 indexer

crontab 设置indexer运转终了后整理实时索引,着重新的max_doc_id泉源培植实时索引

以上就是培植一个自己的搜索引擎的历程。更多装备细节可到官方网站参考文档。


最后更新时间: