| 包 | XS | 
|---|---|
| 继承关系 | class XSSearch » XSServer » XSComponent | 
| 版本 | 1.0.0 | 
| 源代码 | sdk/php/lib/XSSearch.class.php | 
$xs->search->setQuery($str)->setLimit(10, 10)->search(); $xs->close();
| 名称 | 类型 | 描述 | 定义于 | 
|---|---|---|---|
| allSynonyms | array | 获取当前库内的全部同义词列表 | XSSearch | 
| connString | string | 连接字符串 | XSServer | 
| correctedQuery | array | 获取修正后的搜索词列表 | XSSearch | 
| dbTotal | int | 获取搜索数据库内的数据总量 | XSSearch | 
| facets | array | 读取最近一次分面搜索记数 | 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 | 
| 名称 | 类型 | 描述 | 定义于 | 
|---|---|---|---|
| _conn | XSServer | ||
| _flag | XSServer | ||
| _project | XSServer | ||
| _sendBuffer | XSServer | ||
| _sock | XSServer | 
| 名称 | 描述 | 定义于 | 
|---|---|---|
| __construct() | 构造函数, 打开连接 | XSServer | 
| __destruct() | 析构函数, 关闭连接 | XSServer | 
| __get() | 魔术方法 __get | XSComponent | 
| __isset() | 魔术方法 __isset | XSComponent | 
| __set() | 魔术方法 __set | XSComponent | 
| __unset() | 魔术方法 __unset | XSComponent | 
| addDb() | 添加搜索的数据库名, 支持多库同时搜索 | XSSearch | 
| addQueryString() | 增加默认搜索语句 | XSSearch | 
| addQueryTerm() | 增加默认搜索词汇 | XSSearch | 
| addRange() | 添加搜索过滤区间或范围 | XSSearch | 
| addSearchLog() | 添加搜索日志关键词到缓冲区里 | XSSearch | 
| addWeight() | 添加权重索引词 | XSSearch | 
| close() | 关闭连接 | XSServer | 
| count() | 估算搜索语句的匹配数据量 | XSSearch | 
| execCommand() | 执行服务端指令并获取返回值 | XSServer | 
| getAllSynonyms() | 获取当前库内的全部同义词列表 | XSSearch | 
| getConnString() | Returns 连接字符串 | XSServer | 
| getCorrectedQuery() | 获取修正后的搜索词列表 | XSSearch | 
| getDbTotal() | 获取搜索数据库内的数据总量 | XSSearch | 
| getExpandedQuery() | 获取展开的搜索词列表 | XSSearch | 
| getFacets() | 读取最近一次分面搜索记数 | XSSearch | 
| getHotQuery() | 获取热门搜索词列表 | XSSearch | 
| getLastCount() | 获取最近那次搜索的匹配总数估值 | XSSearch | 
| getProject() | 获取当前项目名称 | XSServer | 
| getQuery() | 获取解析后的搜索语句 | XSSearch | 
| getRelatedQuery() | 获取相关搜索词列表 | XSSearch | 
| getRespond() | 从服务器读取响应指令 | XSServer | 
| getSocket() | 获取连接资源描述符 | XSServer | 
| getSynonyms() | 获取指定词汇的同义词列表 | XSSearch | 
| hasRespond() | 判断服务端是否有可读数据 | XSServer | 
| highlight() | 搜索结果字符串高亮处理 | XSSearch | 
| markResetScheme() | 标记字段方案重置 | XSSearch | 
| open() | 连接搜索服务端并初始化 | XSSearch | 
| reopen() | 重新打开连接 | XSServer | 
| search() | 获取匹配的搜索结果文档 | XSSearch | 
| sendCommand() | 往服务器直接发送指令 (无缓存) | XSServer | 
| setAutoSynonyms() | 开启自动同义词搜索功能 | XSSearch | 
| setCharset() | 设置字符集 | XSSearch | 
| setCollapse() | 设置折叠搜索结果 | XSSearch | 
| setCutOff() | 设置百分比/权重剔除参数 | XSSearch | 
| setDb() | 设置要搜索的数据库名 | XSSearch | 
| setDocOrder() | 设置结果按索引入库先后排序 | XSSearch | 
| setFacets() | 设置分面搜索记数 | XSSearch | 
| setFuzzy() | 开启模糊搜索 | XSSearch | 
| setGeodistSort() | 设置地理位置距离排序方式 | XSSearch | 
| setLimit() | 设置搜索结果的数量和偏移 | XSSearch | 
| setMultiSort() | 设置多字段组合排序方式 | XSSearch | 
| setProject() | 设置当前项目 | XSServer | 
| setQuery() | 设置默认搜索语句 | XSSearch | 
| setRequireMatchedTerm() | 设置在搜索结果文档中返回匹配词表 | XSSearch | 
| setScwsMulti() | 设置当前搜索语句的分词复合等级 | XSSearch | 
| setSort() | 设置搜索结果的排序方式 | XSSearch | 
| setSynonymScale() | 设置同义词搜索的权重比例 | XSSearch | 
| setTimeout() | 设置服务端超时秒数 | XSServer | 
| setWeightingScheme() | 设置检索匹配的权重方案 | XSSearch | 
| terms() | 获取搜索语句中的高亮词条列表 | XSSearch | 
| 名称 | 描述 | 定义于 | 
|---|---|---|
| check() | 检测服务端的连接情况 | XSServer | 
| connect() | 连接服务端 | XSServer | 
| read() | 读取数据 | XSServer | 
| write() | 写入数据 | XSServer | 
获取当前库内的全部同义词列表
获取修正后的搜索词列表 通常当某次检索结果数量偏少时, 可以用该函数设计 "你是不是要找: ..." 功能
获取搜索数据库内的数据总量
读取最近一次分面搜索记数 必须在某一次 search 之后调用本函数才有意义
获取热门搜索词列表
获取最近那次搜索的匹配总数估值
获取解析后的搜索语句
获取相关搜索词列表
| 
public XSSearch addDb(string $name) | ||
| $name | string | |
| {return} | XSSearch | 返回对象本身以支持串接操作 | 
public function addDb($name)
{
    $name = strval($name);
    $this->execCommand(array('cmd' => XS_CMD_SEARCH_ADD_DB, 'buf' => $name));
    $this->_curDbs[] = $name;
    return $this;
}
添加搜索的数据库名, 支持多库同时搜索
| 
public string addQueryString(string $query, int $addOp=0, float $scale=1) | ||
| $query | string | 搜索语句 | 
| $addOp | int | 与旧语句的结合操作符, 如果无旧语句或为空则这此无意义, 支持的操作符有: XS_CMD_QUERY_OP_AND XS_CMD_QUERY_OP_OR XS_CMD_QUERY_OP_AND_NOT XS_CMD_QUERY_OP_XOR XS_CMD_QUERY_OP_AND_MAYBE XS_CMD_QUERY_OP_FILTER | 
| $scale | float | 权重计算缩放比例, 默认为 1表示不缩放, 其它值范围 0.xx ~ 655.35 | 
| {return} | string | 修正后的搜索语句 | 
public function addQueryString($query, $addOp = XS_CMD_QUERY_OP_AND, $scale = 1)
{
    $query = $this->preQueryString($query);
    $bscale = ($scale > 0 && $scale != 1) ? pack('n', intval($scale * 100)) : '';
    $cmd = new XSCommand(XS_CMD_QUERY_PARSE, $addOp, $this->_defaultOp, $query, $bscale);
    $this->execCommand($cmd);
    return $query;
}
增加默认搜索语句
| 
public XSSearch addQueryTerm(string $field, string|array $term, int $addOp=0, float $scale=1) | ||
| $field | string | 索引词所属的字段, 若为混合区词汇可设为 null 或 body 型的字段名 | 
| $term | string|array | 索引词或列表 | 
| $addOp | int | 与旧语句的结合操作符, 如果无旧语句或为空则这此无意义, 支持的操作符有: | 
| $scale | float | 权重计算缩放比例, 默认为 1表示不缩放, 其它值范围 0.xx ~ 655.35 | 
| {return} | XSSearch | 返回对象本身以支持串接操作 | 
public function addQueryTerm($field, $term, $addOp = XS_CMD_QUERY_OP_AND, $scale = 1)
{
    $term = XS::convert($term, 'UTF-8', $this->_charset);
    $bscale = ($scale > 0 && $scale != 1) ? pack('n', intval($scale * 100)) : '';
    $vno = $field === null ? XSFieldScheme::MIXED_VNO : $this->xs->getField($field, true)->vno;
    $cmd = XS_CMD_QUERY_TERM;
    if (is_array($term)) {
        if (count($term) === 0) {
            return $this;
        } elseif (count($term) === 1) {
            $term = current($term);
        } else {
            $term = implode("\t", $term);
            $cmd = XS_CMD_QUERY_TERMS;
        }
    }
    $cmd = new XSCommand($cmd, $addOp, $vno, $term, $bscale);
    $this->execCommand($cmd);
    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 === '' || $from === false) {
        $from = null;
    }
    if ($to === '' || $to === false) {
        $to = null;
    }
    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(XS_CMD_QUERY_VALCMP, XS_CMD_QUERY_OP_FILTER, $vno, $to, chr(XS_CMD_VALCMP_LE));
        } elseif ($to === null) {
            $cmd = new XSCommand(XS_CMD_QUERY_VALCMP, XS_CMD_QUERY_OP_FILTER, $vno, $from, chr(XS_CMD_VALCMP_GE));
        } else {
            $cmd = new XSCommand(XS_CMD_QUERY_RANGE, XS_CMD_QUERY_OP_FILTER, $vno, $from, $to);
        }
        $this->execCommand($cmd);
    }
    return $this;
}
添加搜索过滤区间或范围
| 
public void addSearchLog(string $query, int $wdf=1) | ||
| $query | string | 需要记录的数据 | 
| $wdf | int | 需要记录的次数, 默认为 1 | 
public function addSearchLog($query, $wdf = 1)
{
    $cmd = array('cmd' => XS_CMD_SEARCH_ADD_LOG, 'buf' => $query);
    if ($wdf > 1) {
        $cmd['buf1'] = pack('i', $wdf);
    }
    $this->execCommand($cmd, XS_CMD_OK_LOGGED);
}
添加搜索日志关键词到缓冲区里 需要调用 XSIndex::flushLogging 才能确保立即刷新, 否则要隔一段时间
| 
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)
{
    return $this->addQueryTerm($field, $term, XS_CMD_QUERY_OP_AND_MAYBE, $weight);
}
添加权重索引词 无论是否包含这种词都不影响搜索匹配, 但会参与计算结果权重, 使结果的相关度更高
| 
public int count(string $query=NULL) | ||
| $query | string | 搜索语句, 若传入 null 使用默认语句, 调用后会还原默认排序方式 如果搜索语句和最近一次 search 的语句一样, 请改用 getLastCount 以提升效率 最大长度为 80 字节 | 
| {return} | int | 匹配的搜索结果数量, 估算数值 | 
public function count($query = null)
{
    $query = $query === null ? '' : $this->preQueryString($query);
    if ($query === '' && $this->_count !== null) {
        return $this->_count;
    }
    $cmd = new XSCommand(XS_CMD_SEARCH_GET_TOTAL, 0, $this->_defaultOp, $query);
    $res = $this->execCommand($cmd, XS_CMD_OK_SEARCH_TOTAL);
    $ret = unpack('Icount', $res->buf);
    if ($query === '') {
        $this->_count = $ret['count'];
    }
    return $ret['count'];
}
估算搜索语句的匹配数据量
| 
public array getAllSynonyms(int $limit=0, int $offset=0, bool $stemmed=false) | ||
| $limit | int | 数量上限, 若设为 0 则启用默认值 100 个 | 
| $offset | int | 偏移量, 即跳过的结果数量, 默认为 0 | 
| $stemmed | bool | 是否包含处理过的词根同义词, 默认为 false 表示否 | 
| {return} | array | 同义词记录数组, 每个词条为键, 同义词条组成的数组为值 | 
public function getAllSynonyms($limit = 0, $offset = 0, $stemmed = false)
{
    $page = $limit > 0 ? pack('II', intval($offset), intval($limit)) : '';
    $cmd = array('cmd' => XS_CMD_SEARCH_GET_SYNONYMS, 'buf1' => $page);
    $cmd['arg1'] = $stemmed == true ? 1 : 0;
    $res = $this->execCommand($cmd, XS_CMD_OK_RESULT_SYNONYMS);
    $ret = array();
    if (!empty($res->buf)) {
        foreach (explode("\n", $res->buf) as $line) {
            $value = explode("\t", $line);
            $key = array_shift($value);
            $ret[$key] = $value;
        }
    }
    return $ret;
}
获取当前库内的全部同义词列表
| 
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' => XS_CMD_QUERY_GET_CORRECTED, 'buf' => $buf);
        $res = $this->execCommand($cmd, XS_CMD_OK_QUERY_CORRECTED);
        if ($res->buf !== '') {
            $ret = explode("\n", XS::convert($res->buf, $this->_charset, 'UTF-8'));
        }
    } catch (XSException $e) {
        if ($e->getCode() != XS_CMD_ERR_XAPIAN) {
            throw $e;
        }
    }
    return $ret;
}
获取修正后的搜索词列表 通常当某次检索结果数量偏少时, 可以用该函数设计 "你是不是要找: ..." 功能
| 
public int getDbTotal() | ||
| {return} | int | 数据总量 | 
public function getDbTotal()
{
    $cmd = new XSCommand(XS_CMD_SEARCH_DB_TOTAL);
    $res = $this->execCommand($cmd, XS_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' => XS_CMD_QUERY_GET_EXPANDED, 'arg1' => $limit, 'buf' => $buf);
        $res = $this->execCommand($cmd, XS_CMD_OK_RESULT_BEGIN);
        // echo "Raw Query: " . $res->buf . "\n";
        // get result documents
        while (true) {
            $res = $this->getRespond();
            if ($res->cmd == XS_CMD_SEARCH_RESULT_FIELD) {
                $ret[] = XS::convert($res->buf, $this->_charset, 'UTF-8');
            } elseif ($res->cmd == XS_CMD_OK && $res->arg == XS_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() != XS_CMD_ERR_XAPIAN) {
            throw $e;
        }
    }
    return $ret;
}
获取展开的搜索词列表
| 
public array getFacets(string $field=NULL) | ||
| $field | string | 读取分面记数的字段, 若为 null 则返回全部分面搜索记录 | 
| {return} | array | 返回由值和计数组成的关联数组, 若不存在或未曾登记过则返回空数组 | 
public function getFacets($field = null)
{
    if ($field === null) {
        return $this->_facets;
    }
    return isset($this->_facets[$field]) ? $this->_facets[$field] : array();
}
读取最近一次分面搜索记数 必须在某一次 search 之后调用本函数才有意义
| 
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::LOG_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->restoreDb();
    } catch (XSException $e) {
        if ($e->getCode() != XS_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(XS_CMD_QUERY_GET_STRING, 0, $this->_defaultOp, $query);
    $res = $this->execCommand($cmd, XS_CMD_OK_QUERY_STRING);
    if (strpos($res->buf, 'VALUE_RANGE') !== false) {
        $regex = '/(VALUE_RANGE) (\d+) (\S+) (.+?)(?=\))/';
        $res->buf = preg_replace_callback($regex, array($this, 'formatValueRange'), $res->buf);
    }
    if (strpos($res->buf, 'VALUE_GE') !== false || strpos($res->buf, 'VALUE_LE') !== false) {
        $regex = '/(VALUE_[GL]E) (\d+) (.+?)(?=\))/';
        $res->buf = preg_replace_callback($regex, array($this, 'formatValueRange'), $res->buf);
    }
    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)));
    // 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::LOG_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() != XS_CMD_ERR_XAPIAN) {
            throw $e;
        }
    }
    $this->restoreDb();
    $this->xs->restoreScheme();
    $this->_defaultOp = $op;
    return $ret;
}
获取相关搜索词列表
| 
public array getSynonyms(string $term) | ||
| $term | string | 要查询同义词的原词 | 
| {return} | array | 同义词记录数组, 不存在同义词则返回空数组 | 
public function getSynonyms($term)
{
    $term = strval($term);
    if (strlen($term) === 0) {
        return false;
    }
    $cmd = array('cmd' => XS_CMD_SEARCH_GET_SYNONYMS, 'arg1' => 2, 'buf' => $term);
    $res = $this->execCommand($cmd, XS_CMD_OK_RESULT_SYNONYMS);
    $ret = $res->buf === '' ? array() : explode("\n", $res->buf);
    return $ret;
}
获取指定词汇的同义词列表
| 
public string highlight(string $value, $strtr=false) | ||
| $value | string | 需要处理的数据 | 
| $strtr | ||
| {return} | string | 高亮后的数据 | 
public function highlight($value, $strtr = false)
{
    // 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 ?
            strtr($value, $this->_highlight['pairs']) :
            str_replace(array_keys($this->_highlight['pairs']), array_values($this->_highlight['pairs']), $value);
    }
    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, boolean $saveHighlight=true) | ||
| $query | string | 搜索语句, 若传入 null 使用默认语句, 最大长度为 80 字节 | 
| $saveHighlight | boolean | 是否存储查询词用于高亮处理, 默认为 true | 
| {return} | XSDocument[] | 匹配的搜索结果文档列表 | 
public function search($query = null, $saveHighlight = true)
{
    if ($this->_curDb !== self::LOG_DB && $saveHighlight) {
        $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(XS_CMD_SEARCH_GET_RESULT, 0, $this->_defaultOp, $query, $page);
    $res = $this->execCommand($cmd, XS_CMD_OK_RESULT_BEGIN);
    $tmp = unpack('Icount', $res->buf);
    $this->_lastCount = $tmp['count'];
    // load vno map to name of fields
    $ret = $this->_facets = array();
    $vnoes = $this->xs->getScheme()->getVnoMap();
    // get result documents
    while (true) {
        $res = $this->getRespond();
        if ($res->cmd == XS_CMD_SEARCH_RESULT_FACETS) {
            $off = 0;
            while (($off + 6) < strlen($res->buf)) {
                $tmp = unpack('Cvno/Cvlen/Inum', substr($res->buf, $off, 6));
                if (isset($vnoes[$tmp['vno']])) {
                    $name = $vnoes[$tmp['vno']];
                    $value = substr($res->buf, $off + 6, $tmp['vlen']);
                    if (!isset($this->_facets[$name])) {
                        $this->_facets[$name] = array();
                    }
                    $this->_facets[$name][$value] = $tmp['num'];
                }
                $off += $tmp['vlen'] + 6;
            }
        } elseif ($res->cmd == XS_CMD_SEARCH_RESULT_DOC) {
            // got new doc
            $doc = new XSDocument($res->buf, $this->_charset);
            $ret[] = $doc;
        } elseif ($res->cmd == XS_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);
            }
        } elseif ($res->cmd == XS_CMD_SEARCH_RESULT_MATCHED) {
            // matched terms
            if (isset($doc)) {
                $doc->setField('matched', explode(' ', $res->buf), true);
            }
        } elseif ($res->cmd == XS_CMD_OK && $res->arg == XS_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 = $this->_lastCount;
        // trigger log & highlight
        if ($this->_curDb !== self::LOG_DB) {
            $this->logQuery();
            if ($saveHighlight) {
                $this->initHighlight();
            }
        }
    }
    $this->_limit = $this->_offset = 0;
    return $ret;
}
获取匹配的搜索结果文档 默认提取最匹配的前 self::PAGE_SIZE 个结果 如需分页请参见 setLimit 设置, 每次调用本函数后都会还原 setLimit 的设置
| 
public XSSearch setAutoSynonyms(bool $value=true) | ||
| $value | bool | 设为 true 表示开启同义词功能, 设为 false 关闭同义词功能 | 
| {return} | XSSearch | 返回对象本身以支持串接操作 | 
public function setAutoSynonyms($value = true)
{
    $flag = XS_CMD_PARSE_FLAG_BOOLEAN | XS_CMD_PARSE_FLAG_PHRASE | XS_CMD_PARSE_FLAG_LOVEHATE;
    if ($value === true) {
        $flag |= XS_CMD_PARSE_FLAG_AUTO_MULTIWORD_SYNONYMS;
    }
    $cmd = array('cmd' => XS_CMD_QUERY_PARSEFLAG, 'arg' => $flag);
    $this->execCommand($cmd);
    return $this;
}
开启自动同义词搜索功能
| 
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(XS_CMD_SEARCH_SET_COLLAPSE, $max, $vno);
    $this->execCommand($cmd);
    return $this;
}
设置折叠搜索结果 注意, 每当调用 setDb 或 addDb 修改当前数据库时会重置此项设置
| 
public XSSearch setCutOff(int $percent, float $weight=0) | ||
| $percent | int | 剔除匹配百分比低于此值的文档, 值范围 0-100 | 
| $weight | float | 剔除权重低于此值的文档, 值范围 0.1-25.5, 0 表示不剔除 | 
| {return} | XSSearch | 返回对象本身以支持串接操作 | 
public function setCutOff($percent, $weight = 0)
{
    $percent = max(0, min(100, intval($percent)));
    $weight = max(0, (intval($weight * 10) & 255));
    $cmd = new XSCommand(XS_CMD_SEARCH_SET_CUTOFF, $percent, $weight);
    $this->execCommand($cmd);
    return $this;
}
设置百分比/权重剔除参数 通常是在开启 setFuzzy 或使用 OR 连接搜索语句时才需要设置此项
| 
public XSSearch setDb(string $name) | ||
| $name | string | |
| {return} | XSSearch | 返回对象本身以支持串接操作 | 
public function setDb($name)
{
    $name = strval($name);
    $this->execCommand(array('cmd' => XS_CMD_SEARCH_SET_DB, 'buf' => strval($name)));
    $this->_lastDb = $this->_curDb;
    $this->_lastDbs = $this->_curDbs;
    $this->_curDb = $name;
    $this->_curDbs = array();
    return $this;
}
设置要搜索的数据库名 若未设置, 使用默认数据库, 数据库必须位于服务端用户目录下 对于远程数据库, 请使用 stub 文件来支持
| 
public XSSearch setDocOrder(bool $asc=false) | ||
| $asc | bool | 是否为正序排列, 即从先到后, 默认为反序 | 
| {return} | XSSearch | 返回对象本身以支持串接操作 | 
public function setDocOrder($asc = false)
{
    $type = XS_CMD_SORT_TYPE_DOCID | ($asc ? XS_CMD_SORT_FLAG_ASCENDING : 0);
    $cmd = new XSCommand(XS_CMD_SEARCH_SET_SORT, $type);
    $this->execCommand($cmd);
    return $this;
}
设置结果按索引入库先后排序 注意, 此项排序不影响相关排序, 权重高的仍会在前面, 主要适合用于布尔检索
| 
public XSSearch setFacets(mixed $field, bool $exact=false) | ||
| $field | mixed | 要进行分组统计的字段或字段组成的数组, 最多同时支持 8 个 | 
| $exact | bool | 是否要求绝对精确搜索, 这会造成较大的系统开销 | 
| {return} | XSSearch | 返回对象本身以支持串接操作 | 
public function setFacets($field, $exact = false)
{
    $buf = '';
    if (!is_array($field)) {
        $field = array($field);
    }
    foreach ($field as $name) {
        $ff = $this->xs->getField($name);
        if ($ff->type !== XSFieldMeta::TYPE_STRING) {
            throw new XSException("Field `$name' cann't be used for facets search, can only be string type");
        }
        $buf .= chr($ff->vno);
    }
    $cmd = array('cmd' => XS_CMD_SEARCH_SET_FACETS, 'buf' => $buf);
    $cmd['arg1'] = $exact === true ? 1 : 0;
    $this->execCommand($cmd);
    return $this;
}
设置分面搜索记数
用于记录匹配搜索结果中按字段值分组的数量统计, 每次调用 search 后会还原设置
对于多次调用 $exact 参数以最后一次为准, 只支持字段值不超过 255 字节的情况
自 v1.4.10 起自动对空值的字段按 term 分面统计(相当于多值)
| 
public XSSearch setFuzzy(bool $value=true) | ||
| $value | bool | 设为 true 表示开启模糊搜索, 设为 false 关闭模糊搜索 | 
| {return} | XSSearch | 返回对象本身以支持串接操作 | 
public function setFuzzy($value = true)
{
    $this->_defaultOp = $value === true ? XS_CMD_QUERY_OP_OR : XS_CMD_QUERY_OP_AND;
    return $this;
}
开启模糊搜索 默认情况只返回包含所有搜索词的记录, 通过本方法可以获得更多搜索结果
| 
public XSSearch setGeodistSort(array $fields, bool $reverse=false, bool $relevance_first=false) | ||
| $fields | array | 在此定义地理位置信息原点坐标信息,数组至少必须包含2个值 | 
| $reverse | bool | 是否由远及近排序, 默认为由近及远 | 
| $relevance_first | bool | 是否优先相关性排序, 默认为否 | 
| {return} | XSSearch | 返回对象本身以支持串接操作 | 
public function setGeodistSort($fields, $reverse = false, $relevance_first = false)
{
    if (!is_array($fields) || count($fields) < 2) {
        throw new XSException("Fields of `setGeodistSort' should be an array contain two or more elements");
    }
    // [vno][vlen][vbuf] ...
    $buf = '';
    foreach ($fields as $key => $value) {
        $field = $this->xs->getField($key, true);
        if (!$field->isNumeric()) {
            throw new XSException("Type of GeoField `$key' shoud be numeric");
        }
        $vno = $field->vno;
        $vbuf = strval(floatval($value));
        $vlen = strlen($vbuf);
        if ($vlen >= 255) {
            throw new XSException("Value of `$key' too long");
        }
        $buf .= chr($vno) . chr($vlen) . $vbuf;
    }
    $type = XS_CMD_SORT_TYPE_GEODIST;
    if ($relevance_first) {
        $type |= XS_CMD_SORT_FLAG_RELEVANCE;
    }
    if (!$reverse) {
        $type |= XS_CMD_SORT_FLAG_ASCENDING;
    }
    $cmd = new XSCommand(XS_CMD_SEARCH_SET_SORT, $type, 0, $buf);
    $this->execCommand($cmd);
    return $this;
}
设置地理位置距离排序方式
请务必先以 numeric 类型字段定义经纬度坐标字段,例如用 lon 代表经度、lat 代表纬度,
那么设置排序代码如下,必须将经度定义在前纬度在后:
$search->setGeodistSort(array('lon' => 39.18, 'lat' => 120.51));
| 
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 setMultiSort(array $fields, bool $reverse=false, bool $relevance_first=false) | ||
| $fields | array | 排序依据的字段数组, 以字段名称为键, true/false 为值表示正序或逆序 | 
| $reverse | bool | 是否为倒序显示, 默认为正向, 此处和 setSort 略有不同 | 
| $relevance_first | bool | 是否优先相关性排序, 默认为否 | 
| {return} | XSSearch | 返回对象本身以支持串接操作 | 
public function setMultiSort($fields, $reverse = false, $relevance_first = false)
{
    if (!is_array($fields)) {
        return $this->setSort($fields, !$reverse, $relevance_first);
    }
    // [vno][0/1] (0:reverse,1:asc)
    $buf = '';
    foreach ($fields as $key => $value) {
        if (is_bool($value)) {
            $vno = $this->xs->getField($key, true)->vno;
            $asc = $value;
        } else {
            $vno = $this->xs->getField($value, true)->vno;
            $asc = false;
        }
        if ($vno != XSFieldScheme::MIXED_VNO) {
            $buf .= chr($vno) . chr($asc ? 1 : 0);
        }
    }
    if ($buf !== '') {
        $type = XS_CMD_SORT_TYPE_MULTI;
        if ($relevance_first) {
            $type |= XS_CMD_SORT_FLAG_RELEVANCE;
        }
        if (!$reverse) {
            $type |= XS_CMD_SORT_FLAG_ASCENDING;
        }
        $cmd = new XSCommand(XS_CMD_SEARCH_SET_SORT, $type, 0, $buf);
        $this->execCommand($cmd);
    }
    return $this;
}
设置多字段组合排序方式 当您需要根据多个字段的值按不同的方式综合排序时, 请使用这项
| 
public XSSearch setQuery(string $query) | ||
| $query | string | 搜索语句, 设为 null 则清空搜索语句, 最大长度为 80 字节 | 
| {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 setRequireMatchedTerm(bool $value=true) | ||
| $value | bool | 设为 true 表示开启返回, 设为 false 关闭该功能, 默认是不开启 | 
| {return} | XSSearch | 返回对象本身以支持串接操作 | 
public function setRequireMatchedTerm($value = true)
{
    $arg1 = XS_CMD_SEARCH_MISC_MATCHED_TERM;
    $arg2 = $value === true ? 1 : 0;
    $cmd = new XSCommand(XS_CMD_SEARCH_SET_MISC, $arg1, $arg2);
    $this->execCommand($cmd);
    return $this;
}
设置在搜索结果文档中返回匹配词表 请在 search 前调用本方法, 然后使用 XSDocument::matched 获取
| 
public XSSearch setScwsMulti(int $level) | ||
| $level | int | 要设置的分词复合等级 | 
| {return} | XSSearch | 返回自身对象以支持串接操作 | 
public function setScwsMulti($level)
{
    $level = intval($level);
    if ($level >= 0 && $level < 16) {
        $cmd = array('cmd' => XS_CMD_SEARCH_SCWS_SET, 'arg1' => XS_CMD_SCWS_SET_MULTI, 'arg2' => $level);
        $this->execCommand($cmd);
    }
    return $this;
}
设置当前搜索语句的分词复合等级 复合等级是 scws 分词粒度控制的一个重要参数, 是长词细分处理依据, 默认为 3, 值范围 0~15 注意: 这个设置仅直对本次搜索有效, 仅对设置之后的 setQuery 起作用, 由于 query 设计的方式问题, 目前无法支持搜索语句单字切分, 但您可以在模糊检索时设为 0 来关闭复合分词
| 
public XSSearch setSort(string $field, bool $asc=false, bool $relevance_first=false) | ||
| $field | string | 依据指定字段的值排序, 设为 null 则用默认顺序 | 
| $asc | bool | 是否为正序排列, 即从小到大, 从少到多, 默认为反序 | 
| $relevance_first | bool | 是否优先相关性排序, 默认为否 | 
| {return} | XSSearch | 返回对象本身以支持串接操作 | 
public function setSort($field, $asc = false, $relevance_first = false)
{
    if (is_array($field)) {
        return $this->setMultiSort($field, $asc, $relevance_first);
    }
    if ($field === null) {
        $cmd = new XSCommand(XS_CMD_SEARCH_SET_SORT, XS_CMD_SORT_TYPE_RELEVANCE);
    } else {
        $type = XS_CMD_SORT_TYPE_VALUE;
        if ($relevance_first) {
            $type |= XS_CMD_SORT_FLAG_RELEVANCE;
        }
        if ($asc) {
            $type |= XS_CMD_SORT_FLAG_ASCENDING;
        }
        $vno = $this->xs->getField($field, true)->vno;
        $cmd = new XSCommand(XS_CMD_SEARCH_SET_SORT, $type, $vno);
    }
    $this->execCommand($cmd);
    return $this;
}
设置搜索结果的排序方式 注意, 每当调用 setDb 或 addDb 修改当前数据库时会重置排序设定 此函数第一参数的用法与 setMultiSort 兼容, 即也可以用该方法实现多字段排序
| 
public XSSearch setSynonymScale(float $value) | ||
| $value | float | 取值范围 0.01-2.55, 1 表示不调整 | 
| {return} | XSSearch | 返回对象本身以支持串接操作 | 
public function setSynonymScale($value)
{
    $arg1 = XS_CMD_SEARCH_MISC_SYN_SCALE;
    $arg2 = max(0, (intval($value * 100) & 255));
    $cmd = new XSCommand(XS_CMD_SEARCH_SET_MISC, $arg1, $arg2);
    $this->execCommand($cmd);
    return $this;
}
设置同义词搜索的权重比例
| 
public XSSearch setWeightingScheme(int $scheme) | ||
| $scheme | int | 匹配权重方案 | 
| {return} | XSSearch | 返回对象本身以支持串接操作 | 
public function setWeightingScheme($scheme) {
    $arg1 = XS_CMD_SEARCH_MISC_WEIGHT_SCHEME;
    $arg2 = intval($scheme);
    $cmd = new XSCommand(XS_CMD_SEARCH_SET_MISC, $arg1, $arg2);
    $this->execCommand($cmd);
    return $this;
}
设置检索匹配的权重方案 目前支持三种权重方案: 0=BM25/1=Bool/2=Trad
| 
public array terms(string $query=NULL, bool $convert=true) | ||
| $query | string | 搜索语句, 若传入 null 使用默认语句, 最大长度为 80 字节 | 
| $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(XS_CMD_QUERY_GET_TERMS, 0, $this->_defaultOp, $query);
        $res = $this->execCommand($cmd, XS_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;
}
获取搜索语句中的高亮词条列表
| 包 | XS | 
|---|---|
| 继承关系 | class XSSearch » XSServer » XSComponent | 
| 版本 | 1.0.0 | 
| 源代码 | sdk/php/lib/XSSearch.class.php | 
$xs->search->setQuery($str)->setLimit(10, 10)->search(); $xs->close();
| 名称 | 类型 | 描述 | 定义于 | 
|---|---|---|---|
| allSynonyms | array | 获取当前库内的全部同义词列表 | XSSearch | 
| connString | string | 连接字符串 | XSServer | 
| correctedQuery | array | 获取修正后的搜索词列表 | XSSearch | 
| dbTotal | int | 获取搜索数据库内的数据总量 | XSSearch | 
| facets | array | 读取最近一次分面搜索记数 | 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 | 
| 名称 | 类型 | 描述 | 定义于 | 
|---|---|---|---|
| _conn | XSServer | ||
| _flag | XSServer | ||
| _project | XSServer | ||
| _sendBuffer | XSServer | ||
| _sock | XSServer | 
| 名称 | 描述 | 定义于 | 
|---|---|---|
| __construct() | 构造函数, 打开连接 | XSServer | 
| __destruct() | 析构函数, 关闭连接 | XSServer | 
| __get() | 魔术方法 __get | XSComponent | 
| __isset() | 魔术方法 __isset | XSComponent | 
| __set() | 魔术方法 __set | XSComponent | 
| __unset() | 魔术方法 __unset | XSComponent | 
| addDb() | 添加搜索的数据库名, 支持多库同时搜索 | XSSearch | 
| addQueryString() | 增加默认搜索语句 | XSSearch | 
| addQueryTerm() | 增加默认搜索词汇 | XSSearch | 
| addRange() | 添加搜索过滤区间或范围 | XSSearch | 
| addSearchLog() | 添加搜索日志关键词到缓冲区里 | XSSearch | 
| addWeight() | 添加权重索引词 | XSSearch | 
| close() | 关闭连接 | XSServer | 
| count() | 估算搜索语句的匹配数据量 | XSSearch | 
| execCommand() | 执行服务端指令并获取返回值 | XSServer | 
| getAllSynonyms() | 获取当前库内的全部同义词列表 | XSSearch | 
| getConnString() | Returns 连接字符串 | XSServer | 
| getCorrectedQuery() | 获取修正后的搜索词列表 | XSSearch | 
| getDbTotal() | 获取搜索数据库内的数据总量 | XSSearch | 
| getExpandedQuery() | 获取展开的搜索词列表 | XSSearch | 
| getFacets() | 读取最近一次分面搜索记数 | XSSearch | 
| getHotQuery() | 获取热门搜索词列表 | XSSearch | 
| getLastCount() | 获取最近那次搜索的匹配总数估值 | XSSearch | 
| getProject() | 获取当前项目名称 | XSServer | 
| getQuery() | 获取解析后的搜索语句 | XSSearch | 
| getRelatedQuery() | 获取相关搜索词列表 | XSSearch | 
| getRespond() | 从服务器读取响应指令 | XSServer | 
| getSocket() | 获取连接资源描述符 | XSServer | 
| getSynonyms() | 获取指定词汇的同义词列表 | XSSearch | 
| hasRespond() | 判断服务端是否有可读数据 | XSServer | 
| highlight() | 搜索结果字符串高亮处理 | XSSearch | 
| markResetScheme() | 标记字段方案重置 | XSSearch | 
| open() | 连接搜索服务端并初始化 | XSSearch | 
| reopen() | 重新打开连接 | XSServer | 
| search() | 获取匹配的搜索结果文档 | XSSearch | 
| sendCommand() | 往服务器直接发送指令 (无缓存) | XSServer | 
| setAutoSynonyms() | 开启自动同义词搜索功能 | XSSearch | 
| setCharset() | 设置字符集 | XSSearch | 
| setCollapse() | 设置折叠搜索结果 | XSSearch | 
| setCutOff() | 设置百分比/权重剔除参数 | XSSearch | 
| setDb() | 设置要搜索的数据库名 | XSSearch | 
| setDocOrder() | 设置结果按索引入库先后排序 | XSSearch | 
| setFacets() | 设置分面搜索记数 | XSSearch | 
| setFuzzy() | 开启模糊搜索 | XSSearch | 
| setGeodistSort() | 设置地理位置距离排序方式 | XSSearch | 
| setLimit() | 设置搜索结果的数量和偏移 | XSSearch | 
| setMultiSort() | 设置多字段组合排序方式 | XSSearch | 
| setProject() | 设置当前项目 | XSServer | 
| setQuery() | 设置默认搜索语句 | XSSearch | 
| setRequireMatchedTerm() | 设置在搜索结果文档中返回匹配词表 | XSSearch | 
| setScwsMulti() | 设置当前搜索语句的分词复合等级 | XSSearch | 
| setSort() | 设置搜索结果的排序方式 | XSSearch | 
| setSynonymScale() | 设置同义词搜索的权重比例 | XSSearch | 
| setTimeout() | 设置服务端超时秒数 | XSServer | 
| setWeightingScheme() | 设置检索匹配的权重方案 | XSSearch | 
| terms() | 获取搜索语句中的高亮词条列表 | XSSearch | 
| 名称 | 描述 | 定义于 | 
|---|---|---|
| check() | 检测服务端的连接情况 | XSServer | 
| connect() | 连接服务端 | XSServer | 
| read() | 读取数据 | XSServer | 
| write() | 写入数据 | XSServer | 
获取当前库内的全部同义词列表
获取修正后的搜索词列表 通常当某次检索结果数量偏少时, 可以用该函数设计 "你是不是要找: ..." 功能
获取搜索数据库内的数据总量
读取最近一次分面搜索记数 必须在某一次 search 之后调用本函数才有意义
获取热门搜索词列表
获取最近那次搜索的匹配总数估值
获取解析后的搜索语句
获取相关搜索词列表
| 
public XSSearch addDb(string $name) | ||
| $name | string | |
| {return} | XSSearch | 返回对象本身以支持串接操作 | 
public function addDb($name)
{
    $name = strval($name);
    $this->execCommand(array('cmd' => XS_CMD_SEARCH_ADD_DB, 'buf' => $name));
    $this->_curDbs[] = $name;
    return $this;
}
添加搜索的数据库名, 支持多库同时搜索
| 
public string addQueryString(string $query, int $addOp=0, float $scale=1) | ||
| $query | string | 搜索语句 | 
| $addOp | int | 与旧语句的结合操作符, 如果无旧语句或为空则这此无意义, 支持的操作符有: XS_CMD_QUERY_OP_AND XS_CMD_QUERY_OP_OR XS_CMD_QUERY_OP_AND_NOT XS_CMD_QUERY_OP_XOR XS_CMD_QUERY_OP_AND_MAYBE XS_CMD_QUERY_OP_FILTER | 
| $scale | float | 权重计算缩放比例, 默认为 1表示不缩放, 其它值范围 0.xx ~ 655.35 | 
| {return} | string | 修正后的搜索语句 | 
public function addQueryString($query, $addOp = XS_CMD_QUERY_OP_AND, $scale = 1)
{
    $query = $this->preQueryString($query);
    $bscale = ($scale > 0 && $scale != 1) ? pack('n', intval($scale * 100)) : '';
    $cmd = new XSCommand(XS_CMD_QUERY_PARSE, $addOp, $this->_defaultOp, $query, $bscale);
    $this->execCommand($cmd);
    return $query;
}
增加默认搜索语句
| 
public XSSearch addQueryTerm(string $field, string|array $term, int $addOp=0, float $scale=1) | ||
| $field | string | 索引词所属的字段, 若为混合区词汇可设为 null 或 body 型的字段名 | 
| $term | string|array | 索引词或列表 | 
| $addOp | int | 与旧语句的结合操作符, 如果无旧语句或为空则这此无意义, 支持的操作符有: | 
| $scale | float | 权重计算缩放比例, 默认为 1表示不缩放, 其它值范围 0.xx ~ 655.35 | 
| {return} | XSSearch | 返回对象本身以支持串接操作 | 
public function addQueryTerm($field, $term, $addOp = XS_CMD_QUERY_OP_AND, $scale = 1)
{
    $term = XS::convert($term, 'UTF-8', $this->_charset);
    $bscale = ($scale > 0 && $scale != 1) ? pack('n', intval($scale * 100)) : '';
    $vno = $field === null ? XSFieldScheme::MIXED_VNO : $this->xs->getField($field, true)->vno;
    $cmd = XS_CMD_QUERY_TERM;
    if (is_array($term)) {
        if (count($term) === 0) {
            return $this;
        } elseif (count($term) === 1) {
            $term = current($term);
        } else {
            $term = implode("\t", $term);
            $cmd = XS_CMD_QUERY_TERMS;
        }
    }
    $cmd = new XSCommand($cmd, $addOp, $vno, $term, $bscale);
    $this->execCommand($cmd);
    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 === '' || $from === false) {
        $from = null;
    }
    if ($to === '' || $to === false) {
        $to = null;
    }
    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(XS_CMD_QUERY_VALCMP, XS_CMD_QUERY_OP_FILTER, $vno, $to, chr(XS_CMD_VALCMP_LE));
        } elseif ($to === null) {
            $cmd = new XSCommand(XS_CMD_QUERY_VALCMP, XS_CMD_QUERY_OP_FILTER, $vno, $from, chr(XS_CMD_VALCMP_GE));
        } else {
            $cmd = new XSCommand(XS_CMD_QUERY_RANGE, XS_CMD_QUERY_OP_FILTER, $vno, $from, $to);
        }
        $this->execCommand($cmd);
    }
    return $this;
}
添加搜索过滤区间或范围
| 
public void addSearchLog(string $query, int $wdf=1) | ||
| $query | string | 需要记录的数据 | 
| $wdf | int | 需要记录的次数, 默认为 1 | 
public function addSearchLog($query, $wdf = 1)
{
    $cmd = array('cmd' => XS_CMD_SEARCH_ADD_LOG, 'buf' => $query);
    if ($wdf > 1) {
        $cmd['buf1'] = pack('i', $wdf);
    }
    $this->execCommand($cmd, XS_CMD_OK_LOGGED);
}
添加搜索日志关键词到缓冲区里 需要调用 XSIndex::flushLogging 才能确保立即刷新, 否则要隔一段时间
| 
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)
{
    return $this->addQueryTerm($field, $term, XS_CMD_QUERY_OP_AND_MAYBE, $weight);
}
添加权重索引词 无论是否包含这种词都不影响搜索匹配, 但会参与计算结果权重, 使结果的相关度更高
| 
public int count(string $query=NULL) | ||
| $query | string | 搜索语句, 若传入 null 使用默认语句, 调用后会还原默认排序方式 如果搜索语句和最近一次 search 的语句一样, 请改用 getLastCount 以提升效率 最大长度为 80 字节 | 
| {return} | int | 匹配的搜索结果数量, 估算数值 | 
public function count($query = null)
{
    $query = $query === null ? '' : $this->preQueryString($query);
    if ($query === '' && $this->_count !== null) {
        return $this->_count;
    }
    $cmd = new XSCommand(XS_CMD_SEARCH_GET_TOTAL, 0, $this->_defaultOp, $query);
    $res = $this->execCommand($cmd, XS_CMD_OK_SEARCH_TOTAL);
    $ret = unpack('Icount', $res->buf);
    if ($query === '') {
        $this->_count = $ret['count'];
    }
    return $ret['count'];
}
估算搜索语句的匹配数据量
| 
public array getAllSynonyms(int $limit=0, int $offset=0, bool $stemmed=false) | ||
| $limit | int | 数量上限, 若设为 0 则启用默认值 100 个 | 
| $offset | int | 偏移量, 即跳过的结果数量, 默认为 0 | 
| $stemmed | bool | 是否包含处理过的词根同义词, 默认为 false 表示否 | 
| {return} | array | 同义词记录数组, 每个词条为键, 同义词条组成的数组为值 | 
public function getAllSynonyms($limit = 0, $offset = 0, $stemmed = false)
{
    $page = $limit > 0 ? pack('II', intval($offset), intval($limit)) : '';
    $cmd = array('cmd' => XS_CMD_SEARCH_GET_SYNONYMS, 'buf1' => $page);
    $cmd['arg1'] = $stemmed == true ? 1 : 0;
    $res = $this->execCommand($cmd, XS_CMD_OK_RESULT_SYNONYMS);
    $ret = array();
    if (!empty($res->buf)) {
        foreach (explode("\n", $res->buf) as $line) {
            $value = explode("\t", $line);
            $key = array_shift($value);
            $ret[$key] = $value;
        }
    }
    return $ret;
}
获取当前库内的全部同义词列表
| 
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' => XS_CMD_QUERY_GET_CORRECTED, 'buf' => $buf);
        $res = $this->execCommand($cmd, XS_CMD_OK_QUERY_CORRECTED);
        if ($res->buf !== '') {
            $ret = explode("\n", XS::convert($res->buf, $this->_charset, 'UTF-8'));
        }
    } catch (XSException $e) {
        if ($e->getCode() != XS_CMD_ERR_XAPIAN) {
            throw $e;
        }
    }
    return $ret;
}
获取修正后的搜索词列表 通常当某次检索结果数量偏少时, 可以用该函数设计 "你是不是要找: ..." 功能
| 
public int getDbTotal() | ||
| {return} | int | 数据总量 | 
public function getDbTotal()
{
    $cmd = new XSCommand(XS_CMD_SEARCH_DB_TOTAL);
    $res = $this->execCommand($cmd, XS_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' => XS_CMD_QUERY_GET_EXPANDED, 'arg1' => $limit, 'buf' => $buf);
        $res = $this->execCommand($cmd, XS_CMD_OK_RESULT_BEGIN);
        // echo "Raw Query: " . $res->buf . "\n";
        // get result documents
        while (true) {
            $res = $this->getRespond();
            if ($res->cmd == XS_CMD_SEARCH_RESULT_FIELD) {
                $ret[] = XS::convert($res->buf, $this->_charset, 'UTF-8');
            } elseif ($res->cmd == XS_CMD_OK && $res->arg == XS_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() != XS_CMD_ERR_XAPIAN) {
            throw $e;
        }
    }
    return $ret;
}
获取展开的搜索词列表
| 
public array getFacets(string $field=NULL) | ||
| $field | string | 读取分面记数的字段, 若为 null 则返回全部分面搜索记录 | 
| {return} | array | 返回由值和计数组成的关联数组, 若不存在或未曾登记过则返回空数组 | 
public function getFacets($field = null)
{
    if ($field === null) {
        return $this->_facets;
    }
    return isset($this->_facets[$field]) ? $this->_facets[$field] : array();
}
读取最近一次分面搜索记数 必须在某一次 search 之后调用本函数才有意义
| 
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::LOG_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->restoreDb();
    } catch (XSException $e) {
        if ($e->getCode() != XS_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(XS_CMD_QUERY_GET_STRING, 0, $this->_defaultOp, $query);
    $res = $this->execCommand($cmd, XS_CMD_OK_QUERY_STRING);
    if (strpos($res->buf, 'VALUE_RANGE') !== false) {
        $regex = '/(VALUE_RANGE) (\d+) (\S+) (.+?)(?=\))/';
        $res->buf = preg_replace_callback($regex, array($this, 'formatValueRange'), $res->buf);
    }
    if (strpos($res->buf, 'VALUE_GE') !== false || strpos($res->buf, 'VALUE_LE') !== false) {
        $regex = '/(VALUE_[GL]E) (\d+) (.+?)(?=\))/';
        $res->buf = preg_replace_callback($regex, array($this, 'formatValueRange'), $res->buf);
    }
    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)));
    // 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::LOG_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() != XS_CMD_ERR_XAPIAN) {
            throw $e;
        }
    }
    $this->restoreDb();
    $this->xs->restoreScheme();
    $this->_defaultOp = $op;
    return $ret;
}
获取相关搜索词列表
| 
public array getSynonyms(string $term) | ||
| $term | string | 要查询同义词的原词 | 
| {return} | array | 同义词记录数组, 不存在同义词则返回空数组 | 
public function getSynonyms($term)
{
    $term = strval($term);
    if (strlen($term) === 0) {
        return false;
    }
    $cmd = array('cmd' => XS_CMD_SEARCH_GET_SYNONYMS, 'arg1' => 2, 'buf' => $term);
    $res = $this->execCommand($cmd, XS_CMD_OK_RESULT_SYNONYMS);
    $ret = $res->buf === '' ? array() : explode("\n", $res->buf);
    return $ret;
}
获取指定词汇的同义词列表
| 
public string highlight(string $value, $strtr=false) | ||
| $value | string | 需要处理的数据 | 
| $strtr | ||
| {return} | string | 高亮后的数据 | 
public function highlight($value, $strtr = false)
{
    // 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 ?
            strtr($value, $this->_highlight['pairs']) :
            str_replace(array_keys($this->_highlight['pairs']), array_values($this->_highlight['pairs']), $value);
    }
    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, boolean $saveHighlight=true) | ||
| $query | string | 搜索语句, 若传入 null 使用默认语句, 最大长度为 80 字节 | 
| $saveHighlight | boolean | 是否存储查询词用于高亮处理, 默认为 true | 
| {return} | XSDocument[] | 匹配的搜索结果文档列表 | 
public function search($query = null, $saveHighlight = true)
{
    if ($this->_curDb !== self::LOG_DB && $saveHighlight) {
        $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(XS_CMD_SEARCH_GET_RESULT, 0, $this->_defaultOp, $query, $page);
    $res = $this->execCommand($cmd, XS_CMD_OK_RESULT_BEGIN);
    $tmp = unpack('Icount', $res->buf);
    $this->_lastCount = $tmp['count'];
    // load vno map to name of fields
    $ret = $this->_facets = array();
    $vnoes = $this->xs->getScheme()->getVnoMap();
    // get result documents
    while (true) {
        $res = $this->getRespond();
        if ($res->cmd == XS_CMD_SEARCH_RESULT_FACETS) {
            $off = 0;
            while (($off + 6) < strlen($res->buf)) {
                $tmp = unpack('Cvno/Cvlen/Inum', substr($res->buf, $off, 6));
                if (isset($vnoes[$tmp['vno']])) {
                    $name = $vnoes[$tmp['vno']];
                    $value = substr($res->buf, $off + 6, $tmp['vlen']);
                    if (!isset($this->_facets[$name])) {
                        $this->_facets[$name] = array();
                    }
                    $this->_facets[$name][$value] = $tmp['num'];
                }
                $off += $tmp['vlen'] + 6;
            }
        } elseif ($res->cmd == XS_CMD_SEARCH_RESULT_DOC) {
            // got new doc
            $doc = new XSDocument($res->buf, $this->_charset);
            $ret[] = $doc;
        } elseif ($res->cmd == XS_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);
            }
        } elseif ($res->cmd == XS_CMD_SEARCH_RESULT_MATCHED) {
            // matched terms
            if (isset($doc)) {
                $doc->setField('matched', explode(' ', $res->buf), true);
            }
        } elseif ($res->cmd == XS_CMD_OK && $res->arg == XS_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 = $this->_lastCount;
        // trigger log & highlight
        if ($this->_curDb !== self::LOG_DB) {
            $this->logQuery();
            if ($saveHighlight) {
                $this->initHighlight();
            }
        }
    }
    $this->_limit = $this->_offset = 0;
    return $ret;
}
获取匹配的搜索结果文档 默认提取最匹配的前 self::PAGE_SIZE 个结果 如需分页请参见 setLimit 设置, 每次调用本函数后都会还原 setLimit 的设置
| 
public XSSearch setAutoSynonyms(bool $value=true) | ||
| $value | bool | 设为 true 表示开启同义词功能, 设为 false 关闭同义词功能 | 
| {return} | XSSearch | 返回对象本身以支持串接操作 | 
public function setAutoSynonyms($value = true)
{
    $flag = XS_CMD_PARSE_FLAG_BOOLEAN | XS_CMD_PARSE_FLAG_PHRASE | XS_CMD_PARSE_FLAG_LOVEHATE;
    if ($value === true) {
        $flag |= XS_CMD_PARSE_FLAG_AUTO_MULTIWORD_SYNONYMS;
    }
    $cmd = array('cmd' => XS_CMD_QUERY_PARSEFLAG, 'arg' => $flag);
    $this->execCommand($cmd);
    return $this;
}
开启自动同义词搜索功能
| 
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(XS_CMD_SEARCH_SET_COLLAPSE, $max, $vno);
    $this->execCommand($cmd);
    return $this;
}
设置折叠搜索结果 注意, 每当调用 setDb 或 addDb 修改当前数据库时会重置此项设置
| 
public XSSearch setCutOff(int $percent, float $weight=0) | ||
| $percent | int | 剔除匹配百分比低于此值的文档, 值范围 0-100 | 
| $weight | float | 剔除权重低于此值的文档, 值范围 0.1-25.5, 0 表示不剔除 | 
| {return} | XSSearch | 返回对象本身以支持串接操作 | 
public function setCutOff($percent, $weight = 0)
{
    $percent = max(0, min(100, intval($percent)));
    $weight = max(0, (intval($weight * 10) & 255));
    $cmd = new XSCommand(XS_CMD_SEARCH_SET_CUTOFF, $percent, $weight);
    $this->execCommand($cmd);
    return $this;
}
设置百分比/权重剔除参数 通常是在开启 setFuzzy 或使用 OR 连接搜索语句时才需要设置此项
| 
public XSSearch setDb(string $name) | ||
| $name | string | |
| {return} | XSSearch | 返回对象本身以支持串接操作 | 
public function setDb($name)
{
    $name = strval($name);
    $this->execCommand(array('cmd' => XS_CMD_SEARCH_SET_DB, 'buf' => strval($name)));
    $this->_lastDb = $this->_curDb;
    $this->_lastDbs = $this->_curDbs;
    $this->_curDb = $name;
    $this->_curDbs = array();
    return $this;
}
设置要搜索的数据库名 若未设置, 使用默认数据库, 数据库必须位于服务端用户目录下 对于远程数据库, 请使用 stub 文件来支持
| 
public XSSearch setDocOrder(bool $asc=false) | ||
| $asc | bool | 是否为正序排列, 即从先到后, 默认为反序 | 
| {return} | XSSearch | 返回对象本身以支持串接操作 | 
public function setDocOrder($asc = false)
{
    $type = XS_CMD_SORT_TYPE_DOCID | ($asc ? XS_CMD_SORT_FLAG_ASCENDING : 0);
    $cmd = new XSCommand(XS_CMD_SEARCH_SET_SORT, $type);
    $this->execCommand($cmd);
    return $this;
}
设置结果按索引入库先后排序 注意, 此项排序不影响相关排序, 权重高的仍会在前面, 主要适合用于布尔检索
| 
public XSSearch setFacets(mixed $field, bool $exact=false) | ||
| $field | mixed | 要进行分组统计的字段或字段组成的数组, 最多同时支持 8 个 | 
| $exact | bool | 是否要求绝对精确搜索, 这会造成较大的系统开销 | 
| {return} | XSSearch | 返回对象本身以支持串接操作 | 
public function setFacets($field, $exact = false)
{
    $buf = '';
    if (!is_array($field)) {
        $field = array($field);
    }
    foreach ($field as $name) {
        $ff = $this->xs->getField($name);
        if ($ff->type !== XSFieldMeta::TYPE_STRING) {
            throw new XSException("Field `$name' cann't be used for facets search, can only be string type");
        }
        $buf .= chr($ff->vno);
    }
    $cmd = array('cmd' => XS_CMD_SEARCH_SET_FACETS, 'buf' => $buf);
    $cmd['arg1'] = $exact === true ? 1 : 0;
    $this->execCommand($cmd);
    return $this;
}
设置分面搜索记数
用于记录匹配搜索结果中按字段值分组的数量统计, 每次调用 search 后会还原设置
对于多次调用 $exact 参数以最后一次为准, 只支持字段值不超过 255 字节的情况
自 v1.4.10 起自动对空值的字段按 term 分面统计(相当于多值)
| 
public XSSearch setFuzzy(bool $value=true) | ||
| $value | bool | 设为 true 表示开启模糊搜索, 设为 false 关闭模糊搜索 | 
| {return} | XSSearch | 返回对象本身以支持串接操作 | 
public function setFuzzy($value = true)
{
    $this->_defaultOp = $value === true ? XS_CMD_QUERY_OP_OR : XS_CMD_QUERY_OP_AND;
    return $this;
}
开启模糊搜索 默认情况只返回包含所有搜索词的记录, 通过本方法可以获得更多搜索结果
| 
public XSSearch setGeodistSort(array $fields, bool $reverse=false, bool $relevance_first=false) | ||
| $fields | array | 在此定义地理位置信息原点坐标信息,数组至少必须包含2个值 | 
| $reverse | bool | 是否由远及近排序, 默认为由近及远 | 
| $relevance_first | bool | 是否优先相关性排序, 默认为否 | 
| {return} | XSSearch | 返回对象本身以支持串接操作 | 
public function setGeodistSort($fields, $reverse = false, $relevance_first = false)
{
    if (!is_array($fields) || count($fields) < 2) {
        throw new XSException("Fields of `setGeodistSort' should be an array contain two or more elements");
    }
    // [vno][vlen][vbuf] ...
    $buf = '';
    foreach ($fields as $key => $value) {
        $field = $this->xs->getField($key, true);
        if (!$field->isNumeric()) {
            throw new XSException("Type of GeoField `$key' shoud be numeric");
        }
        $vno = $field->vno;
        $vbuf = strval(floatval($value));
        $vlen = strlen($vbuf);
        if ($vlen >= 255) {
            throw new XSException("Value of `$key' too long");
        }
        $buf .= chr($vno) . chr($vlen) . $vbuf;
    }
    $type = XS_CMD_SORT_TYPE_GEODIST;
    if ($relevance_first) {
        $type |= XS_CMD_SORT_FLAG_RELEVANCE;
    }
    if (!$reverse) {
        $type |= XS_CMD_SORT_FLAG_ASCENDING;
    }
    $cmd = new XSCommand(XS_CMD_SEARCH_SET_SORT, $type, 0, $buf);
    $this->execCommand($cmd);
    return $this;
}
设置地理位置距离排序方式
请务必先以 numeric 类型字段定义经纬度坐标字段,例如用 lon 代表经度、lat 代表纬度,
那么设置排序代码如下,必须将经度定义在前纬度在后:
$search->setGeodistSort(array('lon' => 39.18, 'lat' => 120.51));
| 
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 setMultiSort(array $fields, bool $reverse=false, bool $relevance_first=false) | ||
| $fields | array | 排序依据的字段数组, 以字段名称为键, true/false 为值表示正序或逆序 | 
| $reverse | bool | 是否为倒序显示, 默认为正向, 此处和 setSort 略有不同 | 
| $relevance_first | bool | 是否优先相关性排序, 默认为否 | 
| {return} | XSSearch | 返回对象本身以支持串接操作 | 
public function setMultiSort($fields, $reverse = false, $relevance_first = false)
{
    if (!is_array($fields)) {
        return $this->setSort($fields, !$reverse, $relevance_first);
    }
    // [vno][0/1] (0:reverse,1:asc)
    $buf = '';
    foreach ($fields as $key => $value) {
        if (is_bool($value)) {
            $vno = $this->xs->getField($key, true)->vno;
            $asc = $value;
        } else {
            $vno = $this->xs->getField($value, true)->vno;
            $asc = false;
        }
        if ($vno != XSFieldScheme::MIXED_VNO) {
            $buf .= chr($vno) . chr($asc ? 1 : 0);
        }
    }
    if ($buf !== '') {
        $type = XS_CMD_SORT_TYPE_MULTI;
        if ($relevance_first) {
            $type |= XS_CMD_SORT_FLAG_RELEVANCE;
        }
        if (!$reverse) {
            $type |= XS_CMD_SORT_FLAG_ASCENDING;
        }
        $cmd = new XSCommand(XS_CMD_SEARCH_SET_SORT, $type, 0, $buf);
        $this->execCommand($cmd);
    }
    return $this;
}
设置多字段组合排序方式 当您需要根据多个字段的值按不同的方式综合排序时, 请使用这项
| 
public XSSearch setQuery(string $query) | ||
| $query | string | 搜索语句, 设为 null 则清空搜索语句, 最大长度为 80 字节 | 
| {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 setRequireMatchedTerm(bool $value=true) | ||
| $value | bool | 设为 true 表示开启返回, 设为 false 关闭该功能, 默认是不开启 | 
| {return} | XSSearch | 返回对象本身以支持串接操作 | 
public function setRequireMatchedTerm($value = true)
{
    $arg1 = XS_CMD_SEARCH_MISC_MATCHED_TERM;
    $arg2 = $value === true ? 1 : 0;
    $cmd = new XSCommand(XS_CMD_SEARCH_SET_MISC, $arg1, $arg2);
    $this->execCommand($cmd);
    return $this;
}
设置在搜索结果文档中返回匹配词表 请在 search 前调用本方法, 然后使用 XSDocument::matched 获取
| 
public XSSearch setScwsMulti(int $level) | ||
| $level | int | 要设置的分词复合等级 | 
| {return} | XSSearch | 返回自身对象以支持串接操作 | 
public function setScwsMulti($level)
{
    $level = intval($level);
    if ($level >= 0 && $level < 16) {
        $cmd = array('cmd' => XS_CMD_SEARCH_SCWS_SET, 'arg1' => XS_CMD_SCWS_SET_MULTI, 'arg2' => $level);
        $this->execCommand($cmd);
    }
    return $this;
}
设置当前搜索语句的分词复合等级 复合等级是 scws 分词粒度控制的一个重要参数, 是长词细分处理依据, 默认为 3, 值范围 0~15 注意: 这个设置仅直对本次搜索有效, 仅对设置之后的 setQuery 起作用, 由于 query 设计的方式问题, 目前无法支持搜索语句单字切分, 但您可以在模糊检索时设为 0 来关闭复合分词
| 
public XSSearch setSort(string $field, bool $asc=false, bool $relevance_first=false) | ||
| $field | string | 依据指定字段的值排序, 设为 null 则用默认顺序 | 
| $asc | bool | 是否为正序排列, 即从小到大, 从少到多, 默认为反序 | 
| $relevance_first | bool | 是否优先相关性排序, 默认为否 | 
| {return} | XSSearch | 返回对象本身以支持串接操作 | 
public function setSort($field, $asc = false, $relevance_first = false)
{
    if (is_array($field)) {
        return $this->setMultiSort($field, $asc, $relevance_first);
    }
    if ($field === null) {
        $cmd = new XSCommand(XS_CMD_SEARCH_SET_SORT, XS_CMD_SORT_TYPE_RELEVANCE);
    } else {
        $type = XS_CMD_SORT_TYPE_VALUE;
        if ($relevance_first) {
            $type |= XS_CMD_SORT_FLAG_RELEVANCE;
        }
        if ($asc) {
            $type |= XS_CMD_SORT_FLAG_ASCENDING;
        }
        $vno = $this->xs->getField($field, true)->vno;
        $cmd = new XSCommand(XS_CMD_SEARCH_SET_SORT, $type, $vno);
    }
    $this->execCommand($cmd);
    return $this;
}
设置搜索结果的排序方式 注意, 每当调用 setDb 或 addDb 修改当前数据库时会重置排序设定 此函数第一参数的用法与 setMultiSort 兼容, 即也可以用该方法实现多字段排序
| 
public XSSearch setSynonymScale(float $value) | ||
| $value | float | 取值范围 0.01-2.55, 1 表示不调整 | 
| {return} | XSSearch | 返回对象本身以支持串接操作 | 
public function setSynonymScale($value)
{
    $arg1 = XS_CMD_SEARCH_MISC_SYN_SCALE;
    $arg2 = max(0, (intval($value * 100) & 255));
    $cmd = new XSCommand(XS_CMD_SEARCH_SET_MISC, $arg1, $arg2);
    $this->execCommand($cmd);
    return $this;
}
设置同义词搜索的权重比例
| 
public XSSearch setWeightingScheme(int $scheme) | ||
| $scheme | int | 匹配权重方案 | 
| {return} | XSSearch | 返回对象本身以支持串接操作 | 
public function setWeightingScheme($scheme) {
    $arg1 = XS_CMD_SEARCH_MISC_WEIGHT_SCHEME;
    $arg2 = intval($scheme);
    $cmd = new XSCommand(XS_CMD_SEARCH_SET_MISC, $arg1, $arg2);
    $this->execCommand($cmd);
    return $this;
}
设置检索匹配的权重方案 目前支持三种权重方案: 0=BM25/1=Bool/2=Trad
| 
public array terms(string $query=NULL, bool $convert=true) | ||
| $query | string | 搜索语句, 若传入 null 使用默认语句, 最大长度为 80 字节 | 
| $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(XS_CMD_QUERY_GET_TERMS, 0, $this->_defaultOp, $query);
        $res = $this->execCommand($cmd, XS_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;
}
获取搜索语句中的高亮词条列表
2条评论!
当我需要将一堆数据按照距离从近到远的顺序排序时,由于使用setLimit()获取,可能由于索引刷新,造成个别数据重复出现在两次分页中,所以想使用主键排序,然后再去拉取数据。但是,发现以上两个函数无法完美结合。
值范围 0~15 注意: 这个设置仅直对本次搜索有效, 只对本次搜索有效
请到论坛 登录 后刷新本页面!