在一个项目中需要使用全文检索功能,架构w推荐了Apache Solr一个独立的企业级别搜索服务器。于是就顺势了解下这个solr搜索服务器。
简介
官网地址:http://lucene.apache.org/solr/
solr是基于lucene的一个搜索服务器,lucene也是Apache的一个开源项目;
Lucene是apache软件基金会4 jakarta项目组的一个子项目,是一个开放源代码的全文检索引擎工具包,即它不是一个完整的全文检
索引擎,而是一个全文检索引擎的架构,提供了完整的查询引擎和索引引擎,部分文本分析引擎(英文与德文两种西方语言)。
Lucene的目的是为软件开发人员提供一个简单易用的工具包,以方便的在目标系统中实现全文检索的功能,或者是以此为基础建立起
完整的全文检索引擎。--来自百度百科
可以简单的说Lucene就是一个搜索引擎架构,而Solr则是一个搜索服务器的实现。
solr是使用java开发实现,目前已经到4.0版本了,运行需要java1.6或以上版本;基于http get进行xml/json/cvs/binary等格式类型的数据传输。solr的数据都是以document对象进行存储,每一个document都由许多field组成,且每一个document都有一个默认的uniqueid,默认的是id。
solr的安装很简单,下载完成后解压,进入solr/example目录
[php]
user:~/solr/example java -jar start.jar
[/php]
输入http://ip:8983/solr/即可看到solr服务器的管理界面。
solr需要一个java服务器,solr服务器里面自带了jetty服务器所以不需要另立服务器,如果有tomcat也可以直接新开一个端口用来运行。
Dashboard是solr服务器的搭建路径,版本,运行环境,机器的物理内存,File Descriptor Count ,jvm内存使用情况等
Logging 则是运行的记录,包括错误,警告等
core admin则是 Schema 的管理界面,可以查看某个Schema的情况,同事还能新建,删除,优化等
java properties 即运行solr的java的所有详细参数
thread dump 运行线程的详细情况,各种数据跟踪
collection1 则是建立的Schema,可以查看Schema的记录数,版本数;还有如ping,query,config等管理操作
solr与php的结合实现
php的solr接口实现已现有代码实现了。项目地址:http://code.google.com/p/solr-php-client/
不过这里需要注意的是因为solr现在是4.0版本了,该php client实现里面还有几个需要注意的,如service.php 中实现add接口的addDocument方法,4.0版本的add属性参数已有改变,废弃了其中的allowDups,overwritePending,overwriteCommitted这几个参数所以需要将这几个参数去掉,否则solr服务器会报错。
一个很简单的例子
[php]
<?php
require_once 'Apache/Solr/Service.php';
$transportIntance = new Apache_Solr_HttpTransport_Curl();
//$transportIntance = new Apache_Solr_HttpTransport_CurlNoReuse();
// 如果这里有不同的Schema如ASchema与BSchema,则传入的第三个参数就是'/solr/ASchema/'与'/solr/BSchema/'
$solr = new Apache_Solr_Service('192.168.1.10', '8983', '/solr/');
// 检测solr服务是否可用
if($solr->ping()){
$solr->deleteByQuery('*:*');
//
// Create two documents to represent two auto parts.
// In practice, documents would likely be assembled from a
// database query.
// 这里需要注意的是,使用的field必须存在于Schema中,否则document写入不到solr服务器,且检索时会产生
// org.apache.solr.common.SolrException: ERROR: [doc=50cdce141f792] unknown field 'partno'的错误
// 这是需要将partno等schema里面没有的field全部都加入到apache-solr-4.0.0/example/solr/collection1/conf/schema.xml <fields>里面
// 写入到schema的 field 需要注意name与attribute,详细请看http://wiki.apache.org/solr/SchemaXml
// 保存完成后重启服务器
$parts = array(
'spark_plug' => array(
'partno' => 1,
'name' => 'Spark plugdw',
// 'model' => array( 'Boxster', '924' ),
'year' => array( 1999, 2000 ),
'price' => 25.00,
'inStock' => true,
),
'windshield' => array(
'partno' => 2,
'name' => 'Windshield',
// 'model' => array('911', '111'), //multiple values encountered for non multiValued field model:
'year' => array( 1999, 2000 ),
'price' => 15.00,
'inStock' => false,
)
);
$documents = array();
foreach ( $parts as $item => $fields ) {
$part = new Apache_Solr_Document();
$part->id = uniqid();
foreach ( $fields as $key => $value ) {
if ( is_array( $value ) ) {
foreach ( $value as $datum ) {
$part->setMultiValue( $key, $datum );
}
}
else {
$part->$key = $value;
}
}
$documents[] = $part;
}
//var_dump($documents);
// Load the documents into the index
try {
$solr->addDocuments( $documents );
// 这里需要注意在加入document后必须要commit提交到检索索引里面,否则最新写入的内容不会被检索到
$solr->commit();
// optimize索引优化这里会重建索引,每次adddocument时不必要进行,应该放到用户搜索很少的时刻定时执行
// 如每周末的24点执行,crontab也是一个选择
$solr->optimize();
}
catch ( Exception $e ) {
echo $e->getMessage();
}
// Run some queries. Provide the raw path, a starting offset
// for result documents, and the maximum number of result
// documents to return. You can also use a fourth parameter
// to control how results are sorted and highlighted,
// among other options.
//
$offset = 0;
$limit = 10;
$queries = array(
'partno:1',
'name:*w*'
);
foreach ( $queries as $query ) {
$response = $solr->search( $query, $offset, $limit );
if ( $response->getHttpStatus() == 200 ) {
// print_r( $response->getRawResponse() );
if ( $response->response->numFound > 0 ) {
echo "$query <br /><br/>";
foreach ( $response->response->docs as $doc ) {
echo "$doc->partno $doc->name <br />";
}
echo '<br />';
}
}
else {
echo $response->getHttpStatusMessage();
}
}
}else {
die('no connection solr service...');
}
?>
[/php]
solr的query语法
根据不同的需要进行选择。
/**
* query语法
* 查询语法 http://lucene.apache.org/core/3_6_0/queryparsersyntax.html
* 1) title:"The Right Way" AND text:go // 标题的值匹配,AND text:go 表示对title默认的值为go的项进行筛选,但不是必须的
* 2) mod_date:[20020101 TO 20030101] //mod_date日期在20020101与20030101之间的
* 3) title:{Aida TO Carmen} // 标题在Aida 与Carmen之间的集合,但不包括Aida Carmen
* 4) content:"jakarta apache" AND "Apache Lucene" // 搜索的字段必须包含 jakarta apache与Apache Lucene;可以使用&&代替AND
* 5) content:+jakarta lucene // 必须包含jakarta 或可能包含lucene
* 6) content:"jakarta apache" jakarta // 结果中包含jakarta apache或jakarta ;或使用content:"jakarta apache" OR jakarta。可以使用||代替OR
* 7) content:"jakarta apache" NOT "Apache Lucene" // 包含jakarta apache,但不包含Apache Lucene;可以使用! 代替NOT
* 8) content:"jakarta apache" -"Apache Lucene" // 包含jakarta apache,但不包括Apache Lucene;与NOT区别还没明白
* 9) content:(jakarta OR apache) AND website // 使用括号实现子查询,包含jakarta OR apache以及website
* 10) title:(+return +"pink panther") // 使用括号将多个子句合并为一个字段,标题中必须包含单词return以及短语"pink panther"
* 11) title:tes? // 使用? * 来实现内容的搜索
* 12) 支持转移字符的查询,需转移字符包括+ - && || ! ( ) { } [ ] ^ " ~ * ? : \ 可以使用\来转义字符,如title:\(1\+1\)\:2
* 13) title:roam~ // ~表示模糊查询,romam~将查找到foam或roams得单词;roam~0.8表示将得到roam 80%的相似度单词
* 14) content:"jakarta apache"~10 // 临近搜索,检索相隔10个单词的”apache”和”jakarta”
*/
solr的搜索是自动进行分词的,当然这是指英文的空格分词;如果中文需要分词怎么办呢?当然也有有心人已经做出来了,就是这个mmseg4j 作者博客上的简介 作者对于lucene solr很有研究,值得一看。
更多阅读