基于上一篇的环境http://blog.youkuaiyun.com/u011562187/article/details/77720975
今天也做了很多solr在PHP下的测试,学到不少东西。先把昨天java测试环境说一下,再说PHP的。
solr Java客户端环境
1,新建一个java项目;
2.将solr-6.6.0\dist\solrj-lib下的jar包复制到项目lib目录下,将solr-6.6.0\dist下的solr-solrj-6.6.0.jar复制到lib目录下,把所有jar包add to build path;
3编写代码测试,目录结构和代码如下图
java增删改查的具体写法在这里就不说了,因为主要要讲PHP的。
Solr PHP环境
通过官方文档https://wiki.apache.org/solr/IntegratingSolr,我们可以看到各个语言如何集成solr客户端。
PHP的第三方lib也有很多,
我这里随便选了第一个solarium,谁叫他放第一个呢。
然后找到 http://www.solarium-project.org/ 和github网址 https://github.com/solariumphp/solarium
我先把github项目下下来,运行sample。需要composer。
下下来之后我解压到solariumsample下,运行composer install,会自动下载依赖,下好之后目录如下
然后修改examples目录下的config.dist.php配置文件,solr服务器的host,port和path,注意默认的path是/solr是不对了,应该到core层。
<?php
$config = array(
'endpoint' => array(
'localhost' => array(
'host' => '127.0.0.1',
'port' => 8080,
'path' => '/solr/new_core',
)
)
);
配置php服务器环境,然后访问examples下的index.html
http://localhost:8090/examples/index.html 就可以查看demo了,点击check-solarium-and-ping应该出现如下界面
然后我在另一个Thinkphp项目下安装环境,直接在项目根目录下命令行运行
composer require solarium/solarium
就会下载相关依赖。
在某个controller下写了如下测试代码
config.php下添加如下配置
'SOLR_CONFIG'=>array(
'endpoint' => array(
'localhost' => array(
'host' => '127.0.0.1',
'port' => 8080,
'path' => '/solr/new_core',
)
)
),
提取文件内容到solr供搜索
/**
* 添加文件
*/
public function testAddFile()
{
//创建client
require '/vendor/autoload.php';
$client = new \Solarium\Client(C('SOLR_CONFIG'));
//创建一个提取查询
$query = $client->createExtract();
//项目Uploads/solr目录下有一个测试doc文件
$query->setFile($_SERVER['DOCUMENT_ROOT'] . "/Uploads/solr/test.docx");
//solr会将文件的额外信息保存到attr开头的字段中,为什么是attr,这个是和managed-schema文件配置相关的,field,dynamicField,copyField
//你也可以不要这句测试一下看看什么结果,还有一些其他设置也可以自行测试下
$query->setUprefix("attr_");
//$query->addParam("literal.id", "10000");跟下面的$doc->id = '10000';效果一样,设置id,id是必须的。
$query->addParam("fmap.content", "attr_content");//文件内容content映射成attr_content
//$query->setExtractOnly(false);//默认就是false,设置为true的话就只提取文件内容,然后返回(response中获取内容),而不会添加到solr数据中
$doc = $query->createDocument();
$doc->id = '10000';//id不存在是add,id存在是update
$doc->title = '这是我的测试标题';//设置额外的字段
$query->setDocument($doc);
$query->setCommit(true);
//$query->setOmitHeader(false);
$result = $client->extract($query);
// echo 'Add status: ' . $result->getStatus() . '<br/>';
//StatusCode为200表示成功
echo 'Add status: ' . $result->getResponse()->getStatusCode() . '<br/>';
}
上传结果:
服务器后台查询
(你可能看到了一个searchkey字段,这个字段我们稍后讨论,solr的配置选项挺多,需要不停优化)
删除solr数据
public function testDel()
{
require '/vendor/autoload.php';
$client = new \Solarium\Client(C('SOLR_CONFIG'));
$query = $client->createUpdate();
//还记得添加的时候必须设置id吗,可以按id删除,查询删除等
$query->addDeleteById("10000");
//$query->addDeleteQuery("*:*");//删除所有
$query->addCommit();
$result = $client->update($query);
echo 'Delete status: ' . $result->getStatus() . '<br/>';
}
删除结果
在查询一下,已经没有了
客户端查询
public function testQuery()
{
require '/vendor/autoload.php';
$client = new \Solarium\Client(C('SOLR_CONFIG'));
$query = $client->createSelect();
//$query->setQuery("*:*");//查询所有
// $query->setQuery("searchkey:技术");//下面解释
$query->setQuery("title:测试");
//$query->addFilterQuery()//多重条件,还没怎么测试
//返回那些字段,不设置就是所有
$query->setFields("id,title,attr_content");
//分页
$query->setStart(0);
$query->setRows(10);
//高亮相关搜索词
$hl = $query->getHighlighting();
$hl->setFields('title, attr_content');
$hl->setSimplePrefix('<font color="red" >');
$hl->setSimplePostfix('</font>');
// this executes the query and returns the result
$resultset = $client->select($query);
$highlighting = $resultset->getHighlighting();
// display the total number of documents found by solr
echo 'NumFound: ' . $resultset->getNumFound();
// show documents using the resultset iterator
foreach ($resultset as $document) {
echo '<hr/><table>';
// the documents are also iterable, to get all fields
foreach ($document as $field => $value) {
// this converts multivalue fields to a comma-separated string
if (is_array($value)) {
$value = implode(', ', $value);
}
echo '<tr><th>' . $field . '</th><td>' . $value . '</td></tr>';
}
echo '</table><br/><b>Highlighting results:</b><br/>';
// highlighting results can be fetched by document id (the field defined as uniquekey in this schema)
$highlightedDoc = $highlighting->getResult($document->id);
if ($highlightedDoc) {
foreach ($highlightedDoc as $field => $highlight) {
echo implode(' (...) ', $highlight) . '<br/>';
}
}
}
}
查询结果
(这里添加的时候,如何把doc文件前面的一些附加内容(date 2017-08-31T10:28:00Z cp:revision 5 extended-properties:AppVersion……)去掉,还不知道。我知道一种方式,就是extrat的时候,设置extractOnly为true,返回的response里面有一个值只有doc正文内容,然后再add到solr,但是我觉得是不是太麻烦了,是否有参数或者方法可以设置,还需在研究研究。)(9.4日更新,重新设置一遍后没有这个问题了,提取内容也正常了,还不确定是哪里的配置出了问题,WEB-INFO/lib目录下不能乱添东西)
再说说searchkey
我们搜索的时候可能要一个关键词对多个字段搜索,比如搜“计算机”,我们既要把标题中包含“计算机”的条目搜出来,也要把内容中包含计算机的条目搜出来。
我打开我的solr_home\new_core\conf下的managed-schema文件,如下,字段很多,没截全。
可以看到attr_*是dynamicField, 理解了所有匹配形式的都是dynamicField。
field就是些明确的字段
在客户端添加字段的时候,字段必须在这里有定义,明确的或匹配的,否则会报错字段不存在。
说到这儿后台的schema对应的就是这个文件中定义的字段和动态字段
copyfield是啥呢?
就是用于解决上面的问题。把source字段的内容,copy到dest字段。我这里把title字段copy到searchkey字段,把attr_content字段也copy到searchkey字段,添加的时候就会出现上面的searchkey字段,他是一个数组,包含title和attr_content,然后搜索的时候
$query->setQuery("searchkey:技术");
就可以搜索出title或者attr_content包含”技术”的内容了,结果如下
这里只是测试,没考虑效率问题,这里content很长,这样映射的话content的内容相当于存了2遍,存储的时候可能并没有存2遍,但至少传输打印的时候,传了2遍,所以肯定不好,知道道理了,自行优化。
还有些东西没说,也有些东西没研究好,如中文分词,搜索评分系统,搜索过滤,等等。比如我遇到,只搜索一个字母,返回的结果为空,我猜是匹配度太低,所以为空,但有时候我们可能又要这种结果,怎么配置和优化还要再研究。