XSSearch
包 | XS |
---|---|
继承关系 | class XSSearch » XSServer » XSComponent |
版本 | 1.0.0 |
源代码 | sdk/php/lib/XSSearch.class.php |
$xs->search->setQuery($str)->setLimit(10, 10)->search(); $xs->close();
Public 属性
名称 | 类型 | 描述 | 定义于 |
---|---|---|---|
correctedQuery | array | 获取修正后的搜索词列表 | XSSearch |
dbTotal | int | 获取搜索数据库内的数据总量 | XSSearch |
hotQuery | array | 获取热门搜索词列表 | XSSearch |
lastCount | int | 获取最近那次搜索的匹配总数估值 | XSSearch |
project | string | 获取当前项目名称 | XSServer |
query | string | 获取解析后的搜索语句 | XSSearch |
relatedQuery | array | 获取相关搜索词列表 | XSSearch |
respond | XSCommand | 从服务器读取响应指令 | XSServer |
socket | mixed | 获取连接资源描述符 | XSServer |
xs | XS | 服务端关联的 XS 对象 | XSServer |
Public 方法
名称 | 描述 | 定义于 |
---|---|---|
__construct() | 构造函数, 打开连接 | XSServer |
__destruct() | 析构函数, 关闭连接 | XSServer |
__get() | 魔术方法 __get | XSComponent |
__isset() | 魔术方法 __isset | XSComponent |
__set() | 魔术方法 __set | XSComponent |
__unset() | 魔术方法 __unset | XSComponent |
addDb() | 添加搜索的数据库名, 支持多库同时搜索 | XSSearch |
addRange() | 添加搜索过滤区间或范围 | XSSearch |
addWeight() | 添加权重索引词 | XSSearch |
close() | 关闭连接 | XSServer |
count() | 估算搜索语句的匹配数据量 | XSSearch |
execCommand() | 执行服务端指令并获取返回值 | XSServer |
getCorrectedQuery() | 获取修正后的搜索词列表 | XSSearch |
getDbTotal() | 获取搜索数据库内的数据总量 | XSSearch |
getExpandedQuery() | 获取展开的搜索词列表 | XSSearch |
getHotQuery() | 获取热门搜索词列表 | XSSearch |
getLastCount() | 获取最近那次搜索的匹配总数估值 | XSSearch |
getProject() | 获取当前项目名称 | XSServer |
getQuery() | 获取解析后的搜索语句 | XSSearch |
getRelatedQuery() | 获取相关搜索词列表 | XSSearch |
getRespond() | 从服务器读取响应指令 | XSServer |
getSocket() | 获取连接资源描述符 | XSServer |
hasRespond() | 判断服务端是否有可读数据 | XSServer |
highlight() | 搜索结果字符串高亮处理 | XSSearch |
markResetScheme() | 标记字段方案重置 | XSSearch |
open() | 连接搜索服务端并初始化 | XSSearch |
reopen() | 重新打开连接 | XSServer |
search() | 获取匹配的搜索结果文档 | XSSearch |
sendCommand() | 往服务器直接发送指令 (无缓存) | XSServer |
setCharset() | 设置字符集 | XSSearch |
setCollapse() | 设置折叠搜索结果 | XSSearch |
setDb() | 设置要搜索的数据库名 | XSSearch |
setFuzzy() | 开启模糊搜索 | XSSearch |
setLimit() | 设置搜索结果的数量和偏移 | XSSearch |
setProject() | 设置当前项目 | XSServer |
setQuery() | 设置默认搜索语句 | XSSearch |
setSort() | 设置搜索结果的排序方式 | XSSearch |
setTimeout() | 设置服务端超时秒数 | XSServer |
terms() | 获取搜索语句中的高亮词条列表 | XSSearch |
属性明细
获取修正后的搜索词列表 通常当某次检索结果数量偏少时, 可以用该函数设计 "你是不是要找: ..." 功能
获取搜索数据库内的数据总量
获取热门搜索词列表
获取最近那次搜索的匹配总数估值
参见
获取解析后的搜索语句
获取相关搜索词列表
方法明细
public XSSearch addDb(string $name)
| ||
$name | string | |
{return} | XSSearch | 返回对象本身以支持串接操作 |
public function addDb($name)
{
$this->execCommand(array('cmd' => CMD_SEARCH_ADD_DB, 'buf' => strval($name)));
return $this;
}
添加搜索的数据库名, 支持多库同时搜索
参见
public XSSearch addRange(string $field, mixed $from, mixed $to)
| ||
$field | string | |
$from | mixed | 起始值(不包含), 若设为 null 则相当于匹配 <= to (字典顺序) |
$to | mixed | 结束值(包含), 若设为 null 则相当于匹配 >= from (字典顺序) |
{return} | XSSearch | 返回对象本身以支持串接操作 |
public function addRange($field, $from, $to)
{
if ($from !== null || $to !== null)
{
if (strlen($from) > 255 || strlen($to) > 255)
throw new XSException('Value of range is too long');
$vno = $this->xs->getField($field)->vno;
$from = XS::convert($from, 'UTF-8', $this->_charset);
$to = XS::convert($to, 'UTF-8', $this->_charset);
if ($from === null)
$cmd = new XSCommand(CMD_QUERY_VALCMP, CMD_QUERY_OP_FILTER, $vno, $to, chr(CMD_VALCMP_LE));
else if ($to === null)
$cmd = new XSCommand(CMD_QUERY_VALCMP, CMD_QUERY_OP_FILTER, $vno, $from, chr(CMD_VALCMP_GE));
else
$cmd = new XSCommand(CMD_QUERY_RANGE, CMD_QUERY_OP_FILTER, $vno, $from, $to);
$this->execCommand($cmd);
}
return $this;
}
添加搜索过滤区间或范围
public XSSearch addWeight(string $field, string $term, float $weight=1)
| ||
$field | string | 索引词所属的字段 |
$term | string | 索引词 |
$weight | float | 权重计算缩放比例 |
{return} | XSSearch | 返回对象本身以支持串接操作 |
public function addWeight($field, $term, $weight = 1)
{
$this->addQueryTerm($field, $term, CMD_QUERY_OP_AND_MAYBE, $weight);
return $this;
}
添加权重索引词 无论是否包含这种词都不影响搜索匹配, 但会参与计算结果权重, 使结果的相关度更高
参见
public int count(string $query=NULL)
| ||
$query | string | 搜索语句, 若传入 null 使用默认语句, 调用后会还原默认排序方式 如果搜索语句和最近一次 search 的语句一样, 请改用 getLastCount 以提升效率 |
{return} | int | 匹配的搜索结果数量, 估算数值 |
public function count($query = null)
{
$query = $query === null ? '' : $this->preQueryString($query);
if ($query === '' && $this->_count !== null)
return $this->_count;
$cmd = new XSCommand(CMD_SEARCH_GET_TOTAL, 0, $this->_defaultOp, $query);
$res = $this->execCommand($cmd, CMD_OK_SEARCH_TOTAL);
$ret = unpack('Icount', $res->buf);
if ($query === '')
$this->_count = $ret['count'];
return $ret['count'];
}
估算搜索语句的匹配数据量
public array getCorrectedQuery(string $query=NULL)
| ||
$query | string | 需要展开的前缀, 可为拼音、英文、中文 |
{return} | array | 返回搜索词组成的数组 |
public function getCorrectedQuery($query = null)
{
$ret = array();
try
{
if ($query === null)
{
if ($this->_count > 0 && $this->_count > ceil($this->getDbTotal() * 0.001))
return $ret;
$query = $this->cleanFieldQuery($this->_query);
}
if (empty($query) || strpos($query, ':') !== false)
return $ret;
$buf = XS::convert($query, 'UTF-8', $this->_charset);
$cmd = array('cmd' => CMD_QUERY_GET_CORRECTED, 'buf' => $buf);
$res = $this->execCommand($cmd, CMD_OK_QUERY_CORRECTED);
if ($res->buf !== '')
$ret = explode("\n", XS::convert($res->buf, $this->_charset, 'UTF-8'));
}
catch (XSException $e)
{
if ($e->getCode() != CMD_ERR_XAPIAN)
throw $e;
}
return $ret;
}
获取修正后的搜索词列表 通常当某次检索结果数量偏少时, 可以用该函数设计 "你是不是要找: ..." 功能
public int getDbTotal()
| ||
{return} | int | 数据总量 |
public function getDbTotal()
{
$cmd = new XSCommand(CMD_SEARCH_DB_TOTAL);
$res = $this->execCommand($cmd, CMD_OK_DB_TOTAL);
$tmp = unpack('Itotal', $res->buf);
return $tmp['total'];
}
获取搜索数据库内的数据总量
public array getExpandedQuery(string $query, int $limit=10)
| ||
$query | string | 需要展开的前缀, 可为拼音、英文、中文 |
$limit | int | 需要返回的搜索词数量上限, 默认为 10, 最大值为 20 |
{return} | array | 返回搜索词组成的数组 |
public function getExpandedQuery($query, $limit = 10)
{
$ret = array();
$limit = max(1, min(20, intval($limit)));
try
{
$buf = XS::convert($query, 'UTF-8', $this->_charset);
$cmd = array('cmd' => CMD_QUERY_GET_EXPANDED, 'arg1' => $limit, 'buf' => $buf);
$res = $this->execCommand($cmd, CMD_OK_RESULT_BEGIN);
// echo "Raw Query: " . $res->buf . "\n";
// get result documents
while (true)
{
$res = $this->getRespond();
if ($res->cmd == CMD_SEARCH_RESULT_FIELD)
{
$ret[] = XS::convert($res->buf, $this->_charset, 'UTF-8');
}
else if ($res->cmd == CMD_OK && $res->arg == CMD_OK_RESULT_END)
{
// got the end
// echo "Parsed Query: " . $res->buf . "\n";
break;
}
else
{
$msg = 'Unexpected respond in search {CMD:' . $res->cmd . ', ARG:' . $res->arg . '}';
throw new XSException($msg);
}
}
}
catch (XSException $e)
{
if ($e->getCode() != CMD_ERR_XAPIAN)
throw $e;
}
return $ret;
}
获取展开的搜索词列表
public array getHotQuery(int $limit=6, string $type='total')
| ||
$limit | int | 需要返回的热门搜索数量上限, 默认为 6, 最大值为 50 |
$type | string | 排序类型, 默认为 total(搜索总量), 可选值还有 lastnum(上周), currnum(本周) |
{return} | array | 返回以搜索词为键, 搜索指数为值的关联数组 |
public function getHotQuery($limit = 6, $type = 'total')
{
$ret = array();
$limit = max(1, min(50, intval($limit)));
// query from log_db
$this->xs->setScheme(XSFieldScheme::logger());
try
{
$this->setDb(self::LOB_DB)->setLimit($limit);
if ($type !== 'lastnum' && $type !== 'currnum')
$type = 'total';
$result = $this->search($type . ':1');
foreach ($result as $doc) /* @var $doc XSDocument */
{
$body = $doc->body;
$ret[$body] = $doc->f($type);
}
$this->setDb(null);
}
catch (XSException $e)
{
if ($e->getCode() != CMD_ERR_XAPIAN)
throw $e;
}
$this->xs->restoreScheme();
return $ret;
}
获取热门搜索词列表
public int getLastCount()
| ||
{return} | int | 匹配数据量, 如从未搜索则返回 false |
public function getLastCount()
{
return $this->_lastCount;
}
获取最近那次搜索的匹配总数估值
参见
public string getQuery(string $query=NULL)
| ||
$query | string | 搜索语句, 若传入 null 使用默认语句 |
{return} | string | 返回解析后的搜索语句 |
public function getQuery($query = null)
{
$query = $query === null ? '' : $this->preQueryString($query);
$cmd = new XSCommand(CMD_QUERY_GET_STRING, 0, $this->_defaultOp, $query);
$res = $this->execCommand($cmd, CMD_OK_QUERY_STRING);
return XS::convert($res->buf, $this->_charset, 'UTF-8');
}
获取解析后的搜索语句
public array getRelatedQuery(string $query=NULL, int $limit=6)
| ||
$query | string | 搜索语句, 若传入 null 使用默认语句 |
$limit | int | 需要返回的相关搜索数量上限, 默认为 6, 最大值为 20 |
{return} | array | 返回搜索词组成的数组 |
public function getRelatedQuery($query = null, $limit = 6)
{
$ret = array();
$limit = max(1, min(20, intval($limit)));
// trigger to logQuery
$this->logQuery();
// Simple to disable query with field filter
if ($query === null)
$query = $this->cleanFieldQuery($this->_query);
if (empty($query) || strpos($query, ':') !== false)
return $ret;
// Search the log database
$op = $this->_defaultOp;
$this->xs->setScheme(XSFieldScheme::logger());
try
{
$result = $this->setDb(self::LOB_DB)->setFuzzy()->setLimit($limit + 1)->search($query);
foreach ($result as $doc) /* @var $doc XSDocument */
{
$doc->setCharset($this->_charset);
$body = $doc->body;
if (!strcasecmp($body, $query))
continue;
$ret[] = $body;
if (count($ret) == $limit)
break;
}
}
catch (XSException $e)
{
if ($e->getCode() != CMD_ERR_XAPIAN)
throw $e;
}
$this->setDb(null);
$this->xs->restoreScheme();
$this->_defaultOp = $op;
return $ret;
}
获取相关搜索词列表
public string highlight(string $value)
| ||
$value | string | 需要处理的数据 |
{return} | string | 高亮后的数据 |
public function highlight($value)
{
// return empty value directly
if (empty($value))
return $value;
// initlize the highlight replacements
if (!is_array($this->_highlight))
$this->initHighlight();
// process replace
if (isset($this->_highlight['pattern']))
$value = preg_replace($this->_highlight['pattern'], $this->_highlight['replace'], $value);
if (isset($this->_highlight['pairs']))
$value = strtr($value, $this->_highlight['pairs']);
return $value;
}
搜索结果字符串高亮处理 对搜索结果文档的字段进行高亮、飘红处理, 高亮部分加上 em 标记
public void markResetScheme()
|
public function markResetScheme()
{
$this->_resetScheme = true;
}
标记字段方案重置
public void open(string $conn)
| ||
$conn | string |
public function open($conn)
{
parent::open($conn);
$this->_prefix = array();
$this->_fieldSet = false;
$this->_lastCount = false;
}
连接搜索服务端并初始化 每次重新连接后所有的搜索语句相关设置均被还原
public XSDocument[] search(string $query=NULL)
| ||
$query | string | 搜索语句, 若传入 null 使用默认语句 |
{return} | XSDocument[] | 匹配的搜索结果文档列表 |
public function search($query = null)
{
$this->_highlight = $query;
$query = $query === null ? '' : $this->preQueryString($query);
$page = pack('II', $this->_offset, $this->_limit > 0 ? $this->_limit : self::PAGE_SIZE);
// get result header
$cmd = new XSCommand(CMD_SEARCH_GET_RESULT, 0, $this->_defaultOp, $query, $page);
$res = $this->execCommand($cmd, CMD_OK_RESULT_BEGIN);
$tmp = unpack('Icount', $res->buf);
$this->_lastCount = $tmp['count'];
// load vno map to name of fields
$ret = array();
$vnoes = $this->xs->getScheme()->getVnoMap();
// get result documents
while (true)
{
$res = $this->getRespond();
if ($res->cmd == CMD_SEARCH_RESULT_DOC)
{
// got new doc
$doc = new XSDocument($res->buf, $this->_charset);
$ret[] = $doc;
}
else if ($res->cmd == CMD_SEARCH_RESULT_FIELD)
{
// fields of doc
if (isset($doc))
{
$name = isset($vnoes[$res->arg]) ? $vnoes[$res->arg] : $res->arg;
$doc->setField($name, $res->buf);
}
}
else if ($res->cmd == CMD_OK && $res->arg == CMD_OK_RESULT_END)
{
// got the end
break;
}
else
{
$msg = 'Unexpected respond in search {CMD:' . $res->cmd . ', ARG:' . $res->arg . '}';
throw new XSException($msg);
}
}
if ($query === '')
$this->_count = $tmp['count'];
$this->_limit = $this->_offset = 0;
return $ret;
}
获取匹配的搜索结果文档 默认提取最匹配的前 self::PAGE_SIZE 个结果 如需分页请参见 setLimit 设置, 每次调用本函数后都会还原 setLimit 的设置
public XSSearch setCharset(string $charset)
| ||
$charset | string | |
{return} | XSSearch | 返回对象本身以支持串接操作 |
public function setCharset($charset)
{
$this->_charset = strtoupper($charset);
if ($this->_charset == 'UTF8')
$this->_charset = 'UTF-8';
return $this;
}
设置字符集 默认字符集是 UTF-8, 如果您提交的搜索语句和预期得到的搜索结果为其它字符集, 请先设置
public XSSearch setCollapse(string $field, int $num=1)
| ||
$field | string | 依据该字段的值折叠搜索结果, 设为 null 则取消折叠 |
$num | int | 折叠后只是返最匹配的数据数量, 默认为 1, 最大值 255 |
{return} | XSSearch | 返回对象本身以支持串接操作 |
public function setCollapse($field, $num = 1)
{
$vno = $field === null ? XSFieldScheme::MIXED_VNO : $this->xs->getField($field, true)->vno;
$max = min(255, intval($num));
$cmd = new XSCommand(CMD_SEARCH_SET_COLLAPSE, $max, $vno);
$this->execCommand($cmd);
return $this;
}
设置折叠搜索结果
public XSSearch setDb(string $name)
| ||
$name | string | |
{return} | XSSearch | 返回对象本身以支持串接操作 |
public function setDb($name)
{
$this->execCommand(array('cmd' => CMD_SEARCH_SET_DB, 'buf' => strval($name)));
return $this;
}
设置要搜索的数据库名 若未设置, 使用默认数据库, 数据库必须位于服务端用户目录下 对于远程数据库, 请使用 stub 文件来支持
public XSSearch setFuzzy(bool $value=true)
| ||
$value | bool | 设为 true 表示开启模糊搜索, 设为 false 关闭模糊搜索 |
{return} | XSSearch | 返回对象本身以支持串接操作 |
public function setFuzzy($value = true)
{
$this->_defaultOp = $value === true ? CMD_QUERY_OP_OR : CMD_QUERY_OP_AND;
return $this;
}
开启模糊搜索 默认情况只返回包含所有搜索词的记录, 通过本方法可以获得更多搜索结果
public XSSearch setLimit(int $limit, int $offset=0)
| ||
$limit | int | 数量上限, 若设为 0 则启用默认值 self::PAGE_SIZE |
$offset | int | 偏移量, 即跳过的结果数量, 默认为 0 |
{return} | XSSearch | 返回对象本身以支持串接操作 |
public function setLimit($limit, $offset = 0)
{
$this->_limit = intval($limit);
$this->_offset = intval($offset);
return $this;
}
设置搜索结果的数量和偏移 用于搜索结果分页, 每次调用 search 后会还原这2个变量到初始值
public XSSearch setQuery(string $query)
| ||
$query | string | 搜索语句, 设为 null 则清空搜索语句 |
{return} | XSSearch | 返回对象本身以支持串接操作 |
public function setQuery($query)
{
$this->clearQuery();
if ($query !== null)
{
$this->_query = $query;
$this->addQueryString($query);
}
return $this;
}
设置默认搜索语句 用于不带参数的 count 或 search 以及 terms 调用 可与 addWeight 组合运用
public XSSearch setSort(string $field, bool $asc=false)
| ||
$field | string | 依据指定字段的值排序, 设为 null 则用默认顺序 |
$asc | bool | 是否为正序排列, 即从小到大, 从少到多, 默认为反序 |
{return} | XSSearch | 返回对象本身以支持串接操作 |
public function setSort($field, $asc = false)
{
if ($field === null)
$cmd = new XSCommand(CMD_SEARCH_SET_SORT, CMD_SORT_TYPE_RELEVANCE);
else
{
$type = CMD_SORT_TYPE_VALUE | ($asc ? CMD_SORT_FLAG_ASCENDING : 0);
$vno = $this->xs->getField($field, true)->vno;
$cmd = new XSCommand(CMD_SEARCH_SET_SORT, $type, $vno);
}
$this->execCommand($cmd);
return $this;
}
设置搜索结果的排序方式
public array terms(string $query=NULL, bool $convert=true)
| ||
$query | string | 搜索语句, 若传入 null 使用默认语句 |
$convert | bool | 是否进行编码转换, 默认为 true |
{return} | array | 可用于高亮显示的词条列表 |
public function terms($query = null, $convert = true)
{
$query = $query === null ? '' : $this->preQueryString($query);
if ($query === '' && $this->_terms !== null)
$ret = $this->_terms;
else
{
$cmd = new XSCommand(CMD_QUERY_GET_TERMS, 0, $this->_defaultOp, $query);
$res = $this->execCommand($cmd, CMD_OK_QUERY_TERMS);
$ret = array();
$tmps = explode(' ', $res->buf);
for ($i = 0; $i < count($tmps); $i++)
{
if ($tmps[$i] === '' || strpos($tmps[$i], ':') !== false)
continue;
$ret[] = $tmps[$i];
}
if ($query === '')
$this->_terms = $ret;
}
return $convert ? XS::convert($ret, $this->_charset, 'UTF-8') : $ret;
}
获取搜索语句中的高亮词条列表