• 周五. 8月 19th, 2022

5G编程聚合网

5G时代下一个聚合的编程学习网

热门标签

PHP使用Solr(CRUD)

admin

11月 28, 2021

关键字说明 

一.基本查询

  q  查询的关键字,此参数最为重要,例如,q=id:1,默认为q=*:*,

  fl  指定返回哪些字段,用逗号或空格分隔,注意:字段区分大小写,例如,fl= id,title,sort

  start  返回结果的第几条记录开始,一般分页用,默认0开始

  rows  指定返回结果最多有多少条记录,默认值为 10,配合start实现分页

  sort  排序方式,例如id  desc 表示按照 “id” 降序

  wt  (writer type)指定输出格式,有 xml, json, php等

  fq  (filter query)过虑查询,提供一个可选的筛选器查询。返回在q查询符合结果中同时符合的fq条件的查询结果,例如:q=id:1&fq=sort:[1 TO 5],找关键字id为1 的,并且sort是1到5之间的。

  df   默认的查询字段,一般默认指定。

  qt  (query type)指定那个类型来处理查询请求,一般不用指定,默认是standard。

  indent   返回的结果是否缩进,默认关闭,用 indent=true|on 开启,一般调试json,php,phps,ruby输出才有必要用这个参数。

  version   查询语法的版本,建议不使用它,由服务器指定默认值。

  二. Solr的检索运算符

  “:”  指定字段查指定值,如返回所有值*:*

  “?”  表示单个任意字符的通配

  “*”  表示多个任意字符的通配(不能在检索的项开始使用*或者?符号)

  “~”  表示模糊检索,如检索拼写类似于”roam”的项这样写:roam~将找到形如foam和roams的单词;roam~0.8,检索返回相似度在0.8以上的记录。

  AND、||  布尔操作符

  OR、&&  布尔操作符

  NOT、!、-(排除操作符不能单独与项使用构成查询)

  “+”  存在操作符,要求符号”+”后的项必须在文档相应的域中存在²

  ( )  用于构成子查询

  []  包含范围检索,如检索某时间段记录,包含头尾,date:[201507 TO 201510]

  {}  不包含范围检索,如检索某时间段记录,不包含头尾date:{201507 TO 201510}

  三. 高亮

  h1  是否高亮,hl=true,表示采用高亮

  hl.fl  设定高亮显示的字段,用空格或逗号隔开的字段列表。要启用某个字段的highlight功能,就得保证该字段在schema中是stored。如果该参数未被给出,那么就会高亮默认字段 standard handler会用df参数,dismax字段用qf参数。你可以使用星号去方便的高亮所有字段。如果你使用了通配符,那么要考虑启用hl.requiredFieldMatch选项。

  hl.requireFieldMatch   如果置为true,除非用hl.fl指定了该字段,查询结果才会被高亮。它的默认值是false。

  hl.usePhraseHighlighter   如果一个查询中含有短语(引号框起来的)那么会保证一定要完全匹配短语的才会被高亮。

  hl.highlightMultiTerm   如果使用通配符和模糊搜索,那么会确保与通配符匹配的term会高亮。默认为false,同时hl.usePhraseHighlighter要为true。

  hl.fragsize   返回的最大字符数。默认是100.如果为0,那么该字段不会被fragmented且整个字段的值会被返回。

  四. 分组

  官方wiki:http://wiki.apache.org/solr/SimpleFacetParameters#Facet_Fields_and_Facet_Queries

  这是facet的官方wiki,里面有facet各个参数的详细说明。所以这里只说一些常用的。

  Facet是Solr的核心搜索功能,主要是导航(Guided Navigation)、参数化查询(Paramatic Search)。Facet的主要好处是在搜索的同时,可以按照Facet条件进行分组统计,给出导航信息,改善搜索体验。

  Facet主要分为:Field Facet 和  Date Facet 两大类

  1. Field Facet

    facet 参数字段必须被索引

    facet=on 或 facet=true

    facet.field  分组的字段

    facet.prefix  表示Facet字段前缀

    facet.limit   Facet字段返回条数

    facet.offict  开始条数,偏移量,它与facet.limit配合使用可以达到分页的效果

    facet.mincount  Facet字段最小count,默认为0

    facet.missing  如果为on或true,那么将统计那些Facet字段值为null的记录

    facet.sort  表示 Facet 字段值以哪种顺序返回 .格式为 true(count)|false(index,lex),true(count) 表示按照 count 值从大到小排列,false(index,lex) 表示按照字段值的自然顺序 (字母 , 数字的顺序 ) 排列 . 默认情况下为 true(count)

  2. Date Facet

    对日期类型的字段进行 Facet.  Solr 为日期字段提供了更为方便的查询统计方式 .注意 , Date Facet的字段类型必须是 DateField( 或其子类型 ). 需要注意的是 , 使用 Date Facet 时 , 字段名 , 起始时间 , 结束时间 , 时间间隔这 4 个参数都必须提供 .

    facet.date  该参数表示需要进行 Date Facet 的字段名 , 与 facet.field 一样 , 该参数可以被设置多次 , 表示对多个字段进行 Date Facet.

    facet.date.start 起始时间 , 时间的一般格式为 ” 2015-12-31T23:59:59Z”, 另外可以使用 ”NOW”,”YEAR”,”MONTH” 等等 ,

    facet.date.end  结束时间

    facet.date.gap 时间间隔,如果 start 为 2015-1-1,end 为 2016-1-1,gap 设置为 ”+1MONTH” 表示间隔1 个月 , 那么将会把这段时间划分为 12 个间隔段 .

    facet.date.hardend  表示 gap 迭代到 end 时,还剩余的一部分时间段,是否继续去下一个间隔. 取值可以为 true|false, 默认为 false.

    例 start 为 2015-1-1,end 为 2015-12-21,gap 为 ”+1MONTH”, 如果hardend 为 false,则,最后一个时间段为 2015-12-1 至 2016-1-1; 反之,如果 hardend 为 true,则,最后一个时间段为 2015-12-1 至 2015-12-21.

  注意:Facet的字段必须被索引,无需分词,无需存储。无需分词是因为该字段的值代表了一个整体概念,无需存储是因为一般而言用户所关心的并不是该字段的具体值,而是作为对查询结果进行分组的一种手段,给出相关的分组信息,从而改善搜索体验。(关键字说明引用地址:https://www.cnblogs.com/zhangweizhong/p/5056884.html)

代码示例:

<?php
class Solr {
    private static $url; //查询url
    private static $header = array("Content-type:application/json;charset=utf-8");
    private static $host;
    public function __construct($hostname='', $port='', $core='') {
        self::$host = sprintf("http://%s:%s/solr/%s", $hostname, $port, $core);
        self::$url = self::$host . '/select?indent=on&wt=json';
    }

/** * 查询数据 * @param $data */ function getList($data){ $urlstr = self::$url; if(empty($data['catalog'])){ return []; } $urlstr .="&q=catalog:".(int)$data['catalog']; $sqladd = []; $sqaddstr = ''; //考试类型 if (!empty($data['pid'])) { $sqladd[]="pid:".(int)$data['pid']; } if (!empty($data['pids'])) { $sqladd[]= 'pid:'.'('.implode(" ",$data['pids']).')'; } //zb_type 1是直播回放 2是直播 if(!empty($data['start_time']) && !empty($data['end_time'])){ if($data['zb_type'] == 1){ $sqladd[] = 'duration:['.$data['start_time'].' TO *]'; $sqladd[] = 'end_time:[* TO '.$data['end_time'].']'; } if($data['zb_type'] == 2){ $sqladd[] = 'duration:[* TO '.$data['end_time'].']'; $sqladd[] = 'end_time:['.$data['start_time'].' TO *]'; } } if($data['end_time']){ if(is_array($data['end_time'])){ $sqladd[]= 'end_time:['.$data['end_time'][0].' TO '.$data['end_time'][1].']'; } } if($sqladd){ $sqaddstr= "&fq=" . urlencode(implode(' AND ', $sqladd)); } $sqaddstr .= '&sort=duration_s+asc'; $start = $data['start'] ? $data['start'] : 0; $limit = $data['limit'] ? $data['limit'] : 20; $urlstr .="&indent=on&wt=json&start=".$start."&rows=".$limit.$sqaddstr; $list = $this -> curlSolr($urlstr); $qresult=json_decode($list,true); if($qresult&&$qresult['responseHeader']&&$qresult['responseHeader']['status']===0){ return $qresult['response']; }else{ return []; } } /** * 删除数据 * @param $serial string core序列号 * @param $field string 字段名 * @param $val string 值 */ public function delete($serial='',$field='', $val=[]) { if (empty($serial)) return false; $url_str = sprintf(self::$host . "/update?_=%s&boost=1.0&commitWithin=1000&overwrite=true&wt=json", $serial); if (!empty($val)) { if (is_array($val)) { $val = sprintf("(%s)", implode(' ',$val)); }else { $val = sprintf("(%s)", $val); } $delete_data = sprintf('"delete":{"query":"%s:%s"}',$field, $val); }else { $delete_data = '"delete":{"query":"*:*"}'; } $delete_json = "{{$delete_data}}"; return $this -> curlSolr($url_str, $delete_json); } /** * 添加或更新数据 * @param $data array 字段及值 * @param $serial string core序列号 * @return bool true */ public function insert($data, $serial) { $url_str = sprintf(self::$host . "/update?_=%s&boost=1.0&commitWithin=1000&overwrite=true&wt=json", $serial); return $this -> curlSolr($url_str,json_encode($data)); } private function curlSolr($urlstr, $strcenter = ''){ $ch = curl_init(); curl_setopt($ch, CURLOPT_HTTPHEADER, self::$header); curl_setopt($ch, CURLOPT_URL, $urlstr); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); if (!empty($strcenter)) { curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, $strcenter); } $output = curl_exec($ch); curl_close($ch); return $output; } } //实例化对象 $obj = new Solr('127.0.0.1', '8983', 'test'); //测试数据 $data = [ [ 'id' => '1', 'name' => 'Python', 'catalog' => 1, 'catalog_name' => '书籍', 'price' => '23.5', 'description' => '大蟒蛇', 'picture' => '/asd/python.jpg', ], [ 'id' => '2', 'name' => 'C语言', 'catalog' => 1, 'catalog_name' => '书籍', 'price' => '25', 'description' => '我是老大', 'picture' => '/asd/c.jpg', ], [ 'id' => 3, 'pid' => 1, 'sort' => 1, 'remark' => '第一集', 'start_time' => 1628042400, 'end_time' => 1628045100, 'duration' => '45:20', 'duration_s' => '2720', 'zb_type'=>1, 'catalog' => 2, 'catalog_name' => '直播', 'price' => 0, 'description' => '描述描述', 'picture' => '/asd/tv.jpg', ], [ 'id' => 4, 'pid' => 1, 'sort' => 2, 'remark' => '第二集', 'start_time' => 1628132400, 'end_time' => 1628135100, 'duration' => '45:00', 'duration_s' => '2700', 'zb_type'=>2, 'catalog' => 2, 'catalog_name' => '直播', 'price' => 0, 'description' => '很有看点', 'picture' => '/asd/tv.jpg', ], [ 'id' => 5, 'pid' => 1, 'sort' => 3, 'remark' => '第三集', 'start_time' => 1628142400, 'end_time' => 1628145100, 'duration' => '0', 'duration_s' => '0', 'zb_type'=>2, 'catalog' => 2, 'catalog_name' => '直播', 'price' => 0, 'description' => '描述描述', 'picture' => '/asd/tv.jpg', ], ]; //查询 $list = $obj -> getList([ 'catalog' => 2, 'pid' => 1, 'start_time' => 1628046000, 'end_time' => 1628049600, 'zb_type' => 1, ]); echo '<pre>'; var_dump($list);die; //添加或修改 $result = $obj -> insert($data, 1628058275871); var_dump($result);die; //删除 $result = $obj -> delete(1628058275871, 'id', 1); var_dump($result);die;

发表回复

您的电子邮箱地址不会被公开。