-
2009-10-13
提交textarea到mysql,换行 - [php]
郁闷,折腾了半天,提交的数据室带换行的,结果取出来不换行,google了半天,说得云里雾里,一会又是css一会又是js的,最后PHP的nl2br函数搞定。$data = nl2br($data);
真是郁闷,被这个小东西搞了半天,丢人啊
-
2009-08-21
中文全文搜索解决方案sphinx+mysql+mmseg,安装,配置,API调用 - [service]
最近在研究中文搜索引擎,找了许多解决方案,有JAVA下的的Lucene,还有强大的C++下的fietex,哪些比较复杂,对现在的项目来讲,不是很实用,所以把目光瞄向了轻便的sphinx,今天安装还算顺利,以下备忘。
首先,Sphinx默认不支持中文索引及检索,以前用补丁搞定,现在,写补丁那个项目组的人又弄了个CSFT,全称是:CoreSeek Fulltext Search Server,CoreSeek 全文检索服务器。于是呢,就把sphinx集成过来,挺好用的。
1. 去Coreseek官网下载源码,需要mmseg和Coreseek Fulltext Server最好用源码安装,那个RPM文件包反正我没搞定,呵呵。
2. 装mmseg。
# tar zxf mmseg3_0b3.tar.gz
# cd mmseg3_0b4;
# ./configure –prefix=/Data/apps/mmseg (这个目录可以改)
# make && make install
运行mmseg,如果成功会有显示
3. 装CSFT
# tar zxf csft3_0b4.tar.gz
# cd csft3_0b3
# ./configure -prefix=/Data/apps/sphinx (这个需要mysql和mmseg,别把目录写错了)
-with-mysql=/Data/apps/mysql
-with-mmseg=/Data/apps/mmseg
-with-mmseg-includes=/Data/apps/mmseg/include/mmseg
-with-mmseg-libs=/Data/apps/mmseg/lib/
-with-mysql-includes=/Data/apps/mysql/include/mysql/
-with-mysql-libs=/Data/apps/mysql/lib/mysql/
# make && make install
4. sphinx.conf
安装完成后,会生成/Data/apps/sphinx/etc/sphinx.conf.dist 要更改为.conf
#cp /Data/apps/sphinx/etc/sphinx.conf.dist /Data/apps/sphinx/etc/sphinx.conf
5. 生成字典
因为用到中文分词,需要生成字典,去安装目录,比如我的是 /home/changyou/mmseg.3.0b3/data/
#mmseg -u unigram.txt 该命令执行后,将会产生一个名为unigram.txt.uni的文件,将该文件改名为uni.lib,完成词典的构造。
然后,在/Data/apps/sphinx/var/下建立文件夹 dict,然后把uni.lib放进去
6. 配置
sphinx.conf 文件中需要对charset_dictpath指定uni.lib的路径/Data/apps/sphinx/var/dict/
还有连接mysql的信息,这个不用说了罢。
这里有个参数对于中文用户要注意一下:
charset_type
字符集编码类型。可选选项,默认为“sbcs”。已知的值包括“sbcs”和“utf-8”。
对于中文用户,可选的值还可以有“zh_cn.utf-8 ”和“zh_cn.gbk”。当设置charset_type值为上面的两种时,系统默认您开启了中文分词特性。
但是我设置了zh_cn.utf-8,报错说“unknown charset type 'zh_cn.utf-8'”,不知道为什么。。。。。
7. 运行
# /Data/apps/sphinx/bin/indexer
启动索引服务时,如果报下面的错:
error while loading shared libraries: libmysqlclient.so.15: cannot open shared object file: No such file or directory
原因应该是因为mysql的lib文件不在系统的lib搜索路径上导致的。
运行命令,解决:
# ln -s /Data/apps/mysql/lib/mysql/libmysqlclient.so.15 /usr/lib/libmysqlclient.so.15
8. 导入测试数据
# mysql -uroot -p test < /Data/apps/sphinx/etc/example.sql
这里千万注意,mysql编码一定要为UTF-8 !!!
9. 测试建立索引
#indexer --all
出错,Coreseek Full Text Server 3.1
Copyright (c) 2006-2008 coreseek.com
FATAL: no readable config file (looked in /usr/local/sphinx/etc/csft.conf, ./csft.conf)
这是因为 Coreseek 默认要去读 csft.conf,所以要复制一份
# cp /Data/apps/sphinx/etc/sphinx.conf /Data/apps/sphinx/bin/csft.conf
( 或者,也可以指定conf文件,#indexer --config /Data/apps/sphinx/etc/sphinx.conf --all 这里我没有指定,所以用了2个conf文件,很不靠谱)
10. 然后继续运行 #indexer --all ,应该会看到如下输出:
Coreseek Full Text Server 2.1
Copyright (c) 2006-2008 coreseek.com
using config file '/usr/local/etc/csft.conf'...
indexing index 'test1'...
collected 5 docs, 0.0 MB
sorted 0.0 Mhits, 100.0% done
total 5 docs, 230 bytes
total 0.146 sec, 1577.50 bytes/sec, 34.29 docs/sec
indexing index 'test1stemmed'...
collected 5 docs, 0.0 MB
sorted 0.0 Mhits, 100.0% done
total 5 docs, 230 bytes
total 0.011 sec, 21879.74 bytes/sec, 475.65 docs/sec
11. 测试全文检索
# search doc 应该会看到如下输出:
Coreseek Full Text Server 3.1
Copyright (c) 2006-2008 coreseek.com
using config file './csft.conf'...
index 'test1': query 'doc ': returned 2 matches of 2 total in 0.000 sec
displaying matches:
1. document=3, weight=1, group_id=2, date_added=Sat Aug 22 03:54:19 2009
id=3
group_id=2
group_id2=7
date_added=2009-08-22 03:54:19
title=another doc
content=this is another group
2. document=4, weight=1, group_id=2, date_added=Sat Aug 22 03:54:19 2009
id=4
group_id=2
group_id2=8
date_added=2009-08-22 03:54:19
title=doc number four
content=this is to test groups
words:
1. 'doc': 2 documents, 2 hits
index 'test1stemmed': query 'doc ': returned 2 matches of 2 total in 0.000 sec
displaying matches:
1. document=3, weight=1, group_id=2, date_added=Sat Aug 22 03:54:19 2009
id=3
group_id=2
group_id2=7
date_added=2009-08-22 03:54:19
title=another doc
content=this is another group
2. document=4, weight=1, group_id=2, date_added=Sat Aug 22 03:54:19 2009
id=4
group_id=2
group_id2=8
date_added=2009-08-22 03:54:19
title=doc number four
content=this is to test groups
words:1. 'doc': 2 documents, 2 hits
12. 启动searchd进程
# searchd
PHP接口在源安装包下面的api/下,可以调用测试,很好用,明天继续研究!
接上一回,调用sphinx,我们先插入一个中文的数据:
INSERT INTO `test`.`documents` (`id` ,`group_id` ,`group_id2` ,`date_added` ,title` ,`content`)VALUES (NULL , '3', '9', NOW( ) ,'sphinx中文搜索','Sphinx是一个基于SQL的全文检索引擎,可以结合MySQL,PostgreSQL做全文搜索,它可以提供比数据库本身更专业的搜索功能,使得应用程序更容易实现专业化的全文检索。Sphinx特别为一些脚本语言设计搜索API接口,如 PHP,Python,Perl,Ruby等,同时为 MySQL也设计了一个存储引擎插件');
因为有新数据,所以要重建索引(关于这个问题,以后遇到再研究,如果每天有新数据都要重建索引,很不靠谱)
先kill searchd进程,运行:
# searchd --stop 然后
# indexer --all
1.调用sphinx:
一是通过Sphinx官方提供的API接口(接口有Python,Java,Php三种版本)
二是通过安装SphinxSE(具体见1.2部分),然后创建一个中介sphinxSE类型的表,再通过执行特定的SQL语句实现。
现在,我们用API接口,在sphinx安装目录有一个API目录,里面有三个PHP文件:test.php,test2.php和 sphinxapi.php。 sphinxapi.php是sphinx调用接口封装文件,test.php是一个在命令行下执行的查询例子文件,test2.php是一个生成摘要的例子文件。
运行:
# php /home/changyou/csft-3.1/api/test.php -i test1 doc
返回结果:
Query 'doc ' retrieved 2 of 2 matches in 0.000 sec.
Query stats: 'doc' found 2 times in 2 documents
Matches:
1. doc_id=3, weight=100, group_id=2, date_added=2009-08-22 03:54:19
2. doc_id=4, weight=100, group_id=2, date_added=2009-08-22 03:54:19
注意:这里,如果不输入参数 -i test1 doc ,那test.php就不会知道你要查那个索引并且搜索什么字句。
所以,如果想引入生产环境中,我们需要手动修改一下test.php
a. 注释掉10行-43行,
b. 然后添加:$search_info = array("1" => "-i", "2" => "test1", "3" => "$keyword");
c. foreach ( $search_info as $arg ) 替换原来的foreach
d. 自己定义下$keyword="设计",记得把文件另存为utf-8
e. 然后,运行: # php /home/changyou/csft-3.1/api/test.php
Query '(乱码)' retrieved 1 of 1 matches in 0.000 sec.
Query stats:
'(乱码)' found 8 times in 1 documents
Matches:
1. doc_id=5, weight=2, group_id=3, date_added=2009-08-26 20:18:33
哈哈,OK啦!可以将sphinx文件封装好,就可以用与生产环境了。
从上面可以看出Query并不能全部取得我们想要的记录内容,比如说Title,Contents字段就没有取出来,根据官方的说明是sphinx 并没有连到mysql去取记录,只是根据它自己的索引内容进行计算,因此如果想用sphinxAPI去取得我们想要的记录,还必须将Query的结果为依据去查询MySQL才可以得到最终我们想要的结果集。
2.搜索全文时的摘要,高亮显示。
假设我要搜索关键词"test",通过sphinx可以取到搜索结果,在显示搜索结果时,我希望将含有"test"的进行红色或加粗显示,同时,我不希望全部都显示出来,只需要显示一段摘要,就象google或百度那样,搜出来的结果不是全篇显示,只是部分显示,这个就是摘要的作用。
以test2.php中为例,可以利用BuildExcerpts方法可以实现摘要的功能。具体可以看看test2.php的代码。这里不说了。
3.后记
从网上看到,还可以用SphinxSE方式调用Sphinx。但问题是,我安装的时候,不知道为什么没有安装SphinxSE引擎,在mysql 里用mysql> show engine; 查看。可能是我没有直接编译sphinx然后打2个中文补丁吧,而是用了官网推荐的中文搜索安装包。从索引得到ID号,然后再去查询数据库,也可以实现中文搜索的效果,但是具体效率怎么样就不知道了。
最后,在sphinx配置文件里,如要用自己的数据,需要修改源数据,这一项:sql_query = \SELECT id, group_id, UNIX_TIMESTAMP(date_added) AS date_added, title, content \ FROM documents;
让他自己抓取合适你数据结构的语句即可。
参考:http://blog.c1gstudio.com/archives/722 -
2009-08-13
中文分词,应用 - [php]
1.什么是中文分词,以及一些开源项目,见:http://www.williamlong.info/archives/1839.html
2.中文分词一般在搜索的时候用得较多,分词系统一般是基于词频的,并辅以一定的专有名称,人名,地名,数字年代等规则识别来达到基本分词,经小范围测试大概准确率在 90% ~ 95% 之间,已能基本满足一些小型搜索引擎、关键字提取等场合运用。
3.公司现有2个分词系统(开源)
一个是:SCWS(强大,有PHP接口),开发者:Hightman。
一个是:HJ_SegWord(超轻量,用PHP写的)。4.先说Segword,引用类:HJ_SegWord_Class.php,实例化后调用接口:Seg_Word_NM
include_once('HJ_SegWord_Class.php');
$HJ_SegWord = new HJ_Segword_Class();
$keyword = implode(' ', $HJ_SegWord->Seg_Word_NM($keyword));
$HJ_SegWord->Clear();
$keyword = empty($keyword) ? $keyword : conutf8($keyword);
return $keyword;5.至于SCWS,安装见官方文档,使用呢:
$dict = 'lib/pscws/dict/dict.xdb'; //词典
$version = 3; // 采用版本
$autodis = true; // 是否识别名字
$ignore = true; // 是否忽略标点
$debug = false; // 是否为除错模式
$stats = false; // 是否查看统计结果
$object = 'PSCWS' . $version;
require_once('lib/pscws/pscws3.class.php');
$cws = new $object($dict);
$cws->set_ignore_mark($ignore); // 是否忽略标点
$cws->set_autodis($autodis);// 是否识别名字
$cws->set_debug($debug); // 是否为除错模式
// 开启统计
$cws->set_statistics($stats);// 是否查看统计结果
$keyword = implode(' ', $cws->segment($keyword, 'words_cb'));
$keyword = empty($keyword) ? $keyword : conutf8($keyword);return $keyword;
-
2009-04-24
小网站的框架设计要考虑的东西 - [knowledge]
别人的东西,拿来总结下,自己留着看!
架构层次清晰化
起步的阶段应该清楚的确定下来架构的层次。如果都搅和在一起,业务一旦扩增开来,如果原有的一堆东西拆不开就是非常痛苦的事情。
Web Server <--> (AppServer)<-->Cache(eg. Memcached)<-->DB
前端优化很重要
因为流量低,访客可能也不多,这时候值得注意的是页面不要太大,多数流量低的站点吃亏就在于一个页面动辄几兆(我前两天看到一个Startup的首页有4M之大,可谓惊人),用户看个页面半分钟都打不开,你说咋发展? 先把基本的条件满足,再去研究前端优化。
从开始考虑性能
这一点是可选的,但也重要。设计应用的时候在开始就应考虑 Profile 这件事情。一套应用能否在后期进行有效优化和扩展,很大的程度限制在是否有比较合适的 Profile 机制上。需要补充的是,对性能的考虑必然要把有关的历史数据考虑进来。
好架构不是设计出来的
这是最后要补充的一点。好的架构和最初的设计有关系,但最重要的是发展中的演化:
发展-->发现问题-->反馈-->解决问题(执行力)--> 改进->进化到下一阶段--新问题出现(循环) -
2009-04-16







