记录一简单solr操作类
2017-04-01
阅读数:372
solr的php使用有一个比较官方的扩展,百度搜一下会有,使用方法也给出来了,但是本人硬是搞了许久没用起来,所以索性就自己写了一个,功能不多,够自己用,用起来方便。之所以有写这个操作类的想法,是因为solr服务的所有数据访问都可以通过http请求的方式模拟出来,此操作类就是通过组装一条http请求,进而实现操作solr里的数据。操作类目前可以对solr执行新增,修改,查询三种操作,删除操作刚开始考虑到错删的情况所以没加,删除操作个人推荐还是到solr的控制台进行操作,先查询,确认数据,再删,不至于搞错,毕竟数据都是命啊……
配置文件格式:
<?php class Conf { public static $solr_handle = array( 'product' => array('collection' => 'product', 'server' => '192.168.2.220:8983', 'pk' => 'StoreProductId'), 'bproduct' => array('collection' => 'bproduct', 'server' => '192.168.2.220:8983', 'pk' => 'ProductId'), 'pproduct' => array('collection' => 'pproduct', 'server' => '192.168.2.220:8983', 'pk' => 'PStoreProductId'), 'order' => array('collection' => 'order', 'server' => '192.168.2.220:8983', 'pk' => 'OrderID'), ); }
操作类实现:
<?php namespace lib; class Solr { private $where = 'q=*:*'; private $collection; private $action; private $wt = 'json'; //返回格式 private $httpClient; private $host; private $method; private $data = array(); private $body = array(); private $contentType = ''; private $pk; private $fields = ''; private $limit = '&rows=1000&start=0'; private $sort = ''; public $errorMsg = ''; private $sql; public function __construct($collection) { if (!$collection) { throw new \Exception("不合法的collection名称"); } if (!in_array($collection, array_keys(\Conf::$solr_handle))) { throw new \Exception("未配置的collection名称"); } $this->getNode($collection); $this->pk = \Conf::$solr_handle[$collection]['pk']; $this->collection = \Conf::$solr_handle[$collection]['collection']; $this->httpClient = new \Client(); } private function getNode($collection) { $zookeeper = new \MyZookeeper(\Conf::$solrzookeeper); $liveNodes = $zookeeper->getChildren('/live_nodes'); if (!$liveNodes) { throw new \Exception("没有存活的solr节点,请确认zookeeper的solr节点配置项/live_nodes信息"); } $num = rand(0, count($liveNodes) - 1); //若从zookeeper中没有找到存活的solr节点,则使用配置文件中的host $this->host = explode("_", $liveNodes[$num])[0] ? : \Conf::$solr_handle[$collection]['server']; } public function where($column, $op, $value) { $this->where = trim($this->where, "q="); $this->where = trim($this->where, "q=*:*"); switch ($op) { case '=': $this->where .= '+AND+' . $column . ':' . $value; $this->where = trim($this->where, "+AND+"); break; case 'in': $inValue = explode(",", $value); $this->where .= '+AND+('; foreach ($inValue as $v) { $this->where .= $column . ':' . trim($v) . '+OR+'; } $this->where = trim($this->where, "+OR+"); $this->where .= ')'; break; case '>': $this->where .= '+AND+' . $column . ':{' . $value . '+TO+*}'; $this->where = trim($this->where, "+AND+"); break; case '<': $this->where .= '+AND+' . $column . ':{*+TO+' . $value . '}'; $this->where = trim($this->where, "+AND+"); break; case '>=': $this->where .= '+AND+' . $column . ':[' . $value . '+TO+*]'; $this->where = trim($this->where, "+AND+"); break; case '<=': $this->where .= '+AND+' . $column . ':[*+TO+' . $value . ']'; $this->where = trim($this->where, "+AND+"); break; case 'like': $this->where .= '+AND+' . $column . ':*' . $value . '*+'; $this->where = trim($this->where, "+AND+"); break; case 'between': $between = explode(",", urldecode($value)); $this->where .= '+AND+' . $column . ':[' . ($between[0] ? : '*') . '+TO+' . ($between[1]? : '*') . ']'; $this->where = trim($this->where, "+AND+"); break; } $this->where = trim($this->where, "AND+"); $this->where = 'q=' . $this->where; return $this; } public function sort($sort, $type = 'ASC') { $this->sort = '&sort=' . $sort . '+' . $type; return $this; } public function fields($fields) { if (!$fields) { return $this; } $this->fields = '&fl=' . $fields; return $this; } public function limit($rows, $start = 0) { if (!$rows) { return $this; } $this->limit = '&rows=' . (int) $rows . '&start=' . $start; return $this; } public function query() { $this->action = 'select'; $this->method = 'get'; $this->queryPrepare(); return $this->request(); } private function queryPrepare() { $this->data = array(); } public function add($data) { if (is_array(reset($data))) { foreach ($data as &$v) { if (!isset($v[$this->pk])) { throw new \Exception("没有找到主键"); } $v['AddTime'] = date('Y-m-d H:i:s'); } $this->data = json_encode($data); } else { if (!isset($data[$this->pk])) { throw new \Exception("没有找到主键"); } $data['AddTime'] = date('Y-m-d H:i:s'); $this->data = json_encode(array($data)); } $this->action = 'update'; $this->method = 'post'; $this->contentType = 'application/json'; return $this->request(); } public function update($data) { if (!$data) { throw new \Exception("缺少需要更新的数据"); } if ($this->where != 'q=*:*') {//带条件的更新操作 $this->getUpdateData($data); } else { $this->getData($data); } $this->action = 'update'; $this->method = 'post'; $this->contentType = 'application/json'; return $this->request(); } public function setQ($q) { if (!$q) { throw new \Exception('缺少查询条件'); } $this->where = 'q=' . $q; return $this; } /** * 含有查询条件的更新 * @param type $data * @return type */ private function getUpdateData(&$data) { $result = $this->fields($this->pk)->query(); if (!$result['numFound']) { $this->data = json_encode(array()); return; } $selfArr = array(); if (isset($data[$this->pk])) { unset($data[$this->pk]); } foreach ($data as $key => $value) { $selfArr[$key] = array('set' => $value); } foreach ($result['docs'] as $k => $v) { $this->data[$k] = array_merge($selfArr, array( $this->pk => $v[$this->pk], 'UpdateTime' => array('set' => date('Y-m-d H:i:s') ))); } $this->data = json_encode($this->data); } private function getData(&$data) { if (is_array($data[0])) { foreach ($data as $k => $v) { if (!in_array($this->pk, array_keys($v))) { throw new \Exception("没有找到主键"); } foreach ($v as $kk => $vv) { $this->data[$k][$kk] = $kk == $this->pk ? $vv : array('set' => $vv); } $this->data[$k]['UpdateTime'] = array('set' => date('Y-m-d H:i:s')); } } else { if (!in_array($this->pk, array_keys($data))) { throw new \Exception("没有找到主键"); } foreach ($data as $k => $v) { $this->data[0][$k] = $k == $this->pk ? $v : array('set' => $v); } $this->data[0]['UpdateTime'] = array('set' => date('Y-m-d H:i:s')); } $this->data = json_encode($this->data); } public function delete() { $this->request(); } public function getSql() { return $this->sql; } public function getBody() { return $this->body; } private function reset() { $this->body = $this->data; $this->data = array(); $this->where = 'q=*:*'; $this->fields = ''; $this->limit = '&rows=1000&start=0'; $this->sort = ''; } public function request() { $this->sql = 'http://' . $this->host . '/solr/' . $this->collection . '/' . $this->action . '?' . $this->where . $this->fields . $this->sort . $this->limit . '&wt=' . $this->wt; $result = json_decode($this->httpClient->singleRequest($this->sql, $this->method, $this->data, '', $this->contentType), true); $this->reset(); if ($result['responseHeader']['status'] !== 0) { throw new \Exception($result['error']['msg'] . "\n" . 'sql:' . $this->sql . "\n"); } if ($this->action == 'select') { return $result['response']; } return true; } }
操作类支持solr集群模式的使用,因为solr集群本身会借助zookeeper,所以solr集群的各节点状态可以在zookeeper上读取到,其中涉及到的zookeeper扩展的使用可以参考我的博文http://blog.dongguagua.com/Index/detail/Id/16.html
本文中涉及到一个Client类的使用,该类为curl的操作类,用来模拟发送http请求的,读者可以将自己用的http类替换,或者直接用file_get_contents()(不推荐),以下附上该操作类。
<?php /** * Description of Rest * * @author polaris */ class Client { private $options = array( 'timeout' => 2, 'connecttimeout' => 3, ); public function __construct() { $this->options['timeout'] = Conf::$request_time_out ? : 2; $this->options['connecttimeout'] = Conf::$connect_time_out ? : 3; } /** * 向一个url发起请求 * * @param string $url 请求的url地址 * @param string $method 请求的http方法 * @param array $data 请求携带的参数 * @return mixed */ public function singleRequest($url, $method = 'get', $data = array(), $type = 'fields', $content_type = '') { $curl_handle = curl_init(); $method = strtoupper($method); if (is_array($data)) { $data = http_build_query($data); } if ($method == 'GET' && !empty($data)) { $url .= stripos($url, '?') > 0 ? '&' . $data : '?' . $data; } curl_setopt($curl_handle, CURLOPT_URL, $url); curl_setopt($curl_handle, CURLOPT_RETURNTRANSFER, true); curl_setopt($curl_handle, CURLOPT_TIMEOUT, $this->options['timeout']); curl_setopt($curl_handle, CURLOPT_CUSTOMREQUEST, $method); curl_setopt($curl_handle, CURLOPT_HEADER, 0); curl_setopt($curl_handle, CURLOPT_ENCODING, 'gzip,deflate'); if (!empty($content_type)) { curl_setopt($curl_handle, CURLOPT_HTTPHEADER, array('Content-Type:' . $content_type)); } if ($method != 'GET') { curl_setopt($curl_handle, CURLOPT_POST, true); curl_setopt($curl_handle, CURLOPT_POSTFIELDS, $data); } $buffer = curl_exec($curl_handle); curl_close($curl_handle); return $buffer; } } ?>
差不多就这些,希望对刚接触solr的php开发者有些帮助。
本文是博主个人原创,转载的朋友请注明地址,不胜感激:http://blog.dongguagua.com/Index/detail/Id/14.html
前方10米有沙发可抢!
大人,请先右上角登个录 ↑