<p>require 'php/lib/XS.php';</p><p>$xs = new XS('seocn'); // 建立 XS 对象,项目名称为:demo</p><p>$index = $xs->index; // 获取 索引对象</p><p>$doc=new XSDocument;</p><p>$data=array(</p><p>'pid'=>12,</p><p>'subject'=>'测试测试',</p><p>'message'=>'ceshi吃的测试',</p><p>'chrono'=>time());</p><p>print_r($data);</p><p>$doc->setFields($data);</p><p>$index->update($doc);</p><p >php redis 常用</p><p ><span > </span>try{</p><p ><span > </span>$redis=new Redis();</p><p ><span > </span>$redis->connect('121.43.155.130',6579);</p><p ><span > </span>$redis->setex($k,$time,$v);</p><p ><span > </span>}catch(Exception $e){</p><p ><span > </span>global $db;</p><p ><span > </span>$info=$e->getMessage();</p><p ><span > </span>print_r($info);</p><p ><span > </span>//error_save('$redis->set('.$k.','.$v.')',$info);</p><p ><span > </span>return 0;</p><p ><span > </span>}</p><p ><span > </span>try{</p><p ><span > </span>$redis=new Redis();</p><p ><span > </span>$redis->connect('121.43.155.130',6579);</p><p ><span > </span>//$redis->delete($k);</p><p ><span > </span>$v=$redis->get($k);<span > </span></p><p ><span > </span>print_r($v);</p><p ><span > </span>return unserialize($v);</p><p ><span > </span>}catch(Exception $e){</p><p ><span > </span>global $db;</p><p ><span > </span>$info=$e->getMessage();</p><p ><span > </span>print_r($info);</p><p ><span > </span>//error_save('$redis->get('.$k.')',$info);</p><p ><span > </span>return 0;</p><p ><span > </span>}</p><p>require 'php/lib/XS.php';</p><p>$xs = new XS('seocn_article'); // 建立 XS 对象,项目名称为:demo</p><p>$index = $xs->index; // 获取 索引对象</p><p>//添加</p><p><span > </span>$data=array(<br/></p><p><span > </span>'pid'=>$v['id'],</p><p><span > </span>'subject'=>$v['title'],</p><p><span > </span>'message'=>$v['description'],</p><p><span > </span>'chrono'=>$v['atime']</p><p><span > </span>);</p><p><span > </span>$doc->setFields($data);</p><p><span > </span>$index->update($doc);</p><p><span > </span>$id=$v['id'];</p><p>/*<br/></p><p>//更新</p><p>$data=array(</p><p>'pid'=>$id,</p><p>'subject'=>'测试测试',</p><p>'message'=>'ceshi吃的测试',</p><p>'chrono'=>time());</p><p>$doc->setFields($data);</p><p>$index->update($doc);</p><p>//删除</p><p>//1按主键删除</p><p>//$index->del('123');</p><p>//$index->del(array('123','456','12'));</p><p>//2. 按特定字段上的索引词删除</p><p>//$index->del('abc','subject');</p><p>//$index->del(array('abc','def'),'subject');</p><p>//执行清空操作</p><p>//$index->clean();</p><p>//开始搜索</p><p>$search=$xs->search;</p><p>//2. 典型搜索做法</p><p>/*</p><p>一个典型的搜索基本流程是把构建好的搜索语句,通过合适的 API 进行必要的修饰, 再传递给底层的搜索服务器进行处理,然后把匹配的结果返回。具体包括以下步骤:</p><p>构建搜索查询语句 query,然后调用 XSSearch::setQuery 设定它</p><p>根据需要设置附加的查询条件:通过 XSSearch::addWeight 干扰排名权重, 通过 XSSearch::addRange 添加字段搜索区间或范围, 通过 XSSearch::setFuzzy 开启模糊匹配,以获取更多搜索结果</p><p>进行必要的搜索结果限定:通过 XSSearch::setLimit 设置搜索结果数量和偏移, 通过 XSSearch::setSort 设置搜索结果的排序方式,等等</p><p>执行搜索,并获取搜索结果,关于搜索结果的处理详见后面的章节</p><p>代码如下</p><p>$query='php';</p><p>$search->setQuery($query);</p><p>$search->addWeight('subject','xunsearch');</p><p>$search->setLimit(5,10);</p><p>$docs=$search->search();</p><p>echo $count=$search->count();</p><p>/*</p><p>3. 关于快捷搜索</p><p>除了上述的典型搜索方式外,我们还提供一种称为快捷搜索的方式。其实就是直接将 query 语句作为参数传递给相应的 API 调用 XSSearch::count 和 XSSSearch::search。由于不经过 setQuery 因此有些其它辅助的功能受到 限制,比如不能进行结果高亮、不能通过 addWeight、addRange 增加辅助搜索条件。</p><p>$count = $search->count('项目测试');</p><p>$docs = $search->search('项目测试');</p><p>4. 搜索中的串接操作</p><p>由于 Xunsearch PHP-SDK 全面采用面向对象的编程思想,在搜索对象中对部分搜索语句构建、 搜索结果修饰加入了串接操作支持。支持串接操作的方法有:</p><p>addDB($name) - 用于多库搜索,添加数据库名称</p><p>addRange($field, $from, $to) - 添加搜索过滤区间或范围</p><p>addWeight($field, $term) - 添加权重索引词</p><p>setCharset($charset) - 设置字符集</p><p>setCollapse($field, $num = 1) - 设置搜索结果按字段值折叠</p><p>setDb($name) - 设置搜索库名称,默认则为 db</p><p>setFuzzy() - 设置开启模糊搜索, 传入参数 false 可关闭模糊搜索</p><p>setLimit($limit, $offset = 0) - 设置搜索结果返回的数量和偏移</p><p>setQuery($query) - 设置搜索语句</p><p>setSort($field, $asc = false) - 设置搜索结果按字段值排序</p><p>如果采用串接操作,那么上面的搜索语句可以改写如下,有种一气呵成的感觉:</p><p>$docs = $search->setQuery('项目测试')->addWeight('subject', 'xunsearch')->setLimit(5, 10)->search();</p><p>5. 搜索日志</p><p>在每一次正常搜索之后,系统内部均对相应的关键词做了记录和一并分析。但这个行为并不是实时的, 而是积累一定的量后再统一分析和处理。</p><p>搜索日志保存在 $prefix/项目名/log_db 中,它是一个独立的索引库,通过它实现了包括相关搜索、 拼音搜索、纠错建议等功能。</p><p>*/</p><p>//1. 典型搜索语句</p><p>/*</p><p>$search->search('上海人民公园'); // 检索 body 型字段及混合区</p><p>$search->search('上海 人民公园'); // 用空格连接 2 个关键词, 这种情况比上面的用法更明确</p><p>$search->search('subject:上海 人民公园'); // 特别要求 subject 字段包含 "上海"</p><p>$search->setFuzzy()->search('上海公园'); // 开启模糊搜索,搜索 "上海" 或 "公园"</p><p>$search->search('杭州 西湖');</p><p>$search->search('杭州 AND 西湖'); // 这两者效果是相同的</p><p></p><p>$search->setFuzzy()->search('杭州 西湖');</p><p>$search->search('杭州 OR 西湖'); // 这两者效果相同,都是只要求匹配其中一个</p><p></p><p>$search->search('杭州 XOR 西湖'); // 表示必须包含其中一个词,并且不允许同时包含这两词。</p><p>要求搜索结果中不含特定关键词</p><p>$search->search('神雕侠侣 -电视剧'); // 正确用法1</p><p>$search->search('神雕侠侣 NOT 电视剧'); // 正确用法2</p><p></p><p>$search->search('神雕侠侣-电视剧'); // 不符合预期目的</p><p>$search->search('神雕侠侣 - 电视剧'); // 不符合预期目的</p><p>组合关系的括号表达式</p><p>就像数学表达式中,括号具有显式的优先级,如果您需要非常复杂的搜索条件,就采用括号表达式来组合上述的条件。</p><p>// 要求结果包含 "杭州+西湖" 或 "杭州 + 西溪湿地",并且不能包含 "汽车 火车"</p><p>$search->search('((杭州 AND 西湖) OR (杭州 AND 西溪湿地)) NOT (汽车 火车)');</p><p>使用双引号进行精确匹配</p><p>如果输入的查询词较长,在经过系统词法分析后,给出的搜索结果中的查询词,可能是拆分的。 如果您对这种情况不满意,可以尝试给查询短句加上双引号,搜索结果就会要求词按顺序匹配。</p><p>$search->search('上海科技大学');</p><p>// 这时内部把搜索语句切割为:上海+科技+大学,要求搜索结果同时包含这三个词即可,</p><p>// 但不要求它们的出现顺序,有可能先出现"科技"再出现"上海",也有可能这三个词离得很远。</p><p></p><p>$search->search('"上海科技大学"');</p><p>// 加上引号后,要求搜索结果必须依次出现"上海+科技+大学",要显得精准很多。</p><p>索引词之间的距离查询</p><p>如果您希望输入的多个关键词之间的在匹配结果中的位置距离不要太远,那么可以使用 NEAR 语法来进行搜索,默认要求它们的距离不超过 10。您还可以在 NEAR 后加上 /n 表示 具体的距离要求,n 是整数,这儿的距离指的是分词后的序号距离。</p><p>$search->search('杭州 NEAR 西湖'); // 要求结果中出现 "杭州" 和 "西湖",并且距离不超过 10 个词</p><p>$search->search('杭州 NEAR/5 西湖'); // 要求它们距离不超过 5个词</p><p>如果您还希望检索结果中词汇出现的顺序与您的输入顺序一致,只要将 NEAR 换成 ADJ 即可, 注意这些语法词和布尔搜索一样,均必须全部大写。</p><p>$search->search('杭州 ADJ 西湖'); // 要求结果中先出现 "杭州" 再出现 "西湖",并且距离不超过 10 个词</p><p>$search->search('杭州 ADJ/3 西湖'); // 要求它们距离不超过 3个词</p><p>索引词之间的距离查询</p><p>如果您希望输入的多个关键词之间的在匹配结果中的位置距离不要太远,那么可以使用 NEAR 语法来进行搜索,默认要求它们的距离不超过 10。您还可以在 NEAR 后加上 /n 表示 具体的距离要求,n 是整数,这儿的距离指的是分词后的序号距离。</p><p>$search->search('杭州 NEAR 西湖'); // 要求结果中出现 "杭州" 和 "西湖",并且距离不超过 10 个词</p><p>$search->search('杭州 NEAR/5 西湖'); // 要求它们距离不超过 5个词</p><p>如果您还希望检索结果中词汇出现的顺序与您的输入顺序一致,只要将 NEAR 换成 ADJ 即可, 注意这些语法词和布尔搜索一样,均必须全部大写。</p><p>$search->search('杭州 ADJ 西湖'); // 要求结果中先出现 "杭州" 再出现 "西湖",并且距离不超过 10 个词</p><p>$search->search('杭州 ADJ/3 西湖'); // 要求它们距离不超过 3个词</p><p>4. 其它搜索语句修饰</p><p>前面还有提到一些附加的搜索语句修饰,这些操作不能直接写进 Query 语句,只能过过相应的 API 来完成。</p><p>字段值区间搜索</p><p>通过 XSSearch::addRange 我们可以在搜索中,针对某个字段的值增加区间条件过滤。该方法接受三个参数, 第一参数 $field 为字段名称,后面两个参数依次是 $from 起始值,$to 结束值。假设该字段的值为 $value,那么要求 $value > $from && $value <= $to 才符合条件,其中如果有一个设为 null, 则会自动将区间转换为单向比较。</p><p>以前面提到的 demo 项目中的 chrono 字段为例,参看下面代码及注释:</p><p>$from = strtotime("2011-1-1"); // 起始时间 2011年1月1日</p><p>$to = strtotime("2011-9-1"); // 结束时间 2011年9月1日</p><p></p><p>// 1. <= $to: 要求结果的时间必须在 2011-9-1 之前,并且包含 2011-9-1</p><p>$docs = $search->setQuery('杭州')->addRange('chrono', null, $to)->search();</p><p></p><p>// 2. >= $from: 要求结果的时间必须在 2011-1-1 之后,并且包含 2011-1-1</p><p>$docs = $search->setQuery('杭州')->addRange('chrono', $from, null)->search();</p><p></p><p>// 3. > $from && <= $to: 要求结果的时间必须在 2011-1-1 之后 并且 2011-9-1 之前</p><p>$docs = $search->setQuery('杭州')->addRange('chrono', $from, $to)->search();</p><p>按字段索引词加权</p><p>通过 XSSearch::addWeight 我们可以针对某个字段添加权重索引词。该字段是否包含这个词 都不影响搜索匹配结果,但如果包含会参与计算结果权重,使结果的相关度更高。常用于针对某一类 数据提升搜索结果排序位置。</p><p>// 搜索包含 "杭州" 的结果,并且提升 subject 字段包含 "西湖" 的数据的排序</p><p>$docs = $search->setQuery('杭州')->addWeight('subject', '西湖')->search();</p><p>Note: 这些修饰不能应用到快捷搜索中,也就是说不能直接把 Query 语句传递给 XSSearch::search。 您必须用 XSSearch::setQuery 设置搜索语句,再用不带参数的调用 search 或 count 方法。</p><p>区间搜索默认用的是字节序比较,如果您希望将字段值以数字方式比较大小,请将字段的类型设置为 numeric。</p><p>5. 查看搜索语句的分析结果</p><p>通过 XSSearch::setQuery 设置了搜索语句后,您可以调用 XSSearch::getQuery 查看您的搜索语句 在内部的分析结果,常用于 DEBUG。此外这两个方法也可以通过魔术属性 XSSearch::query 来访问。</p><p>// 设置搜索语句方法1:</p><p>$search->setQuery('神雕侠侣 -电视剧');</p><p></p><p>// 设置搜索语句方法2:</p><p>$search->query = '神雕侠侣 -电视剧';</p><p></p><p>// 查看搜索语句解析结果方法1:</p><p>// 不带参数,输出:Xapian::Query((神雕侠侣:(pos=1) AND_NOT 电视剧:(pos=2)))</p><p>echo $search->getQuery();</p><p></p><p>// 带参数,则解析新语句,输出:Xapian::Query((杭州:(pos=1) AND 西湖:(pos=2)))</p><p>echo $search->getQuery('杭州 西湖');</p><p></p><p>// 查看搜索语句解析结果方法2:</p><p>// 相当于不带参数的调用 getQuery()</p><p>echo $search->query;</p><p>*/</p><p>/*获取搜索结果</p><p>获取搜索结果是进行搜索的最主要目的。通过 XSSearch::search 获得搜索结果文档, 如果没有任何符合条件的匹配则会返回一个空数组。</p><p>在获取搜索结果前您必须用上一章学到的知识先构造好相应的搜索语句 $query。</p><p>Note: 只有不带参数的 XSSearch::search 搜索调用才会将关键词记录搜索日志中去。</p><p>1. 设置分页、数量</p><p>默认情况下,每次返回搜索结果的前 10 条数据,您可以通过 XSSearch::setLimit 指定返回的条数及偏移量, 这样就可以实现分页搜索的效果。特别注意,每一次调用 XSSearch::search 后均会把这些设置恢复到默认值状态。</p><p>$search->setLimit(5); // 设置返回结果为前 5 条</p><p>$search->setLimit(5, 15); // 设置返回结果为 5 条,但要先跳过 15 条,即第 16~20 条。</p><p>2. 设置排序方式</p><p>默认情况,搜索结果根据内部算法计算相关度进行排序,采用著名的 BM25 算法,这在信息检索概率模型中表现 非常优秀,通常只要使用默认的算法即可。</p><p>通过 XSSearch::setSort 我们可以指定让搜索结果按照某一个字段的值进行正序或倒序排列,参考代码:</p><p>$search->setSort('chrono'); // 按 chrono 字段的值倒序</p><p>$search->setSort('chrono', true); // 按 chrono 字段的值正序排列</p><p>自从 1.1.0 版本起,通过 XSSearch::setMultiSort 可以实现按照多字段的值排序, 它接受一个数组参数用于表述排序的方式。以字段名称为键,用 true/false 值来表示是否需要正序排列, 默认为 false 表示逆序排列。参见以下代码:</p><p>// 表示先以 chrono 正序、再以 pid 逆序(pid 是字符串并不是数值所以 12 会排在 3 之后)</p><p>$sorts = array('chrono' => true, 'pid' => false);</p><p></p><p>// 如果直接把字段名作为数组的值,默认对该字段采用逆序,因此以上用法和下面用法是完全一样的</p><p>$sorts = array('chrono', 'pid' => false);</p><p></p><p>// 设置搜索排序</p><p>$search->setMultiSort($sorts);</p><p>3. 读取搜索结果文档</p><p>调用 XSSearch::search 后返回的是搜索结果文档对象组成的数组, 您直接使用这些文档对象的属性即可。</p><p>// 以 demo 项目的配置为例</p><p>$docs = $search->setQuery('测试')->setLimit(5)->search();</p><p>foreach ($docs as $doc)</p><p>{</p><p> // 其中常用魔术方法:percent() 表示匹配度百分比, rank() 表示匹配结果序号</p><p> echo $doc->rank() . '. ' . $doc->subject . " [" . $doc->percent() . "%] - ";</p><p> echo date("Y-m-d", $doc->chrono) . "\n" . $doc->message . "\n";</p><p>}</p><p>4. 搜索结果高亮处理</p><p>根据搜索的习惯,通会希望让搜索结果中匹配关键词的部分进行飘红或加粗等高亮处理, 由于其中涉及到了分词等细节处理比较麻烦。因此,我们统一提供了 XSSearch::highlight 方法,可以对搜索结果文档中的字段值直接进行处理,匹配关键词部分会自动套上 em 标签。</p><p>您只要在 CSS 中定义它即可实现自己的高亮代码。</p><p>$docs = $search->setQuery('测试')->setLimit(5)->search();</p><p>foreach ($docs as $doc)</p><p>{</p><p> $subject = $search->highlight($doc->subject); // 高亮处理 subject 字段</p><p> $message = $search->highlight($doc->message); // 高亮处理 message 字段</p><p> echo $doc->rank() . '. ' . $subject . " [" . $doc->percent() . "%] - ";</p><p> echo date("Y-m-d", $doc->chrono) . "\n" . $message . "\n";</p><p>}</p><p>Note: 这个方法不适合于快捷搜索,也就是说必须使用 setQuery 以及不带参数的 search 才有效。</p><p>5. 按字段值折叠搜索结果</p><p>有时我们也反折叠搜索称为归并搜索,就像 Google 上通常搜索结果中对于某一个网站只会显示 2 条最匹配的结果, 其余的归并折叠起来。</p><p>在 Xunsearch 中,通过 XSSearch::setCollapse 可以设置按照指定字段的值归并搜索结果,其中第二参数可以 指定归并后返回数量,默认为 1。对于这种情况,请在搜索结果文档中调用 $doc->ccount() 获取展开的全部匹配数。</p><p>// 表示搜索结果按 tid 字段的值归并,至多返回 1 条最匹配的数据</p><p>$search->setCollapse('tid');</p><p></p><p>// 然后正常进行搜索后得到的搜索结果文档</p><p>$docs = $search->search();</p><p></p><p>foreach ($docs as $doc)</p><p>{</p><p> // 输出 $doc 的有关信息</p><p></p><p> // 得出相同 tid 下还有多少条匹配信息</p><p> echo '该主是下还有 ' . ($doc->ccount() - 1) . ' 条匹配结果。';</p><p>}</p><p>//获取搜索结果</p><p>$docs=$search->setQuery('php')->setLimit(5)->search();</p><p>foreach($docs as $v){</p><p><span > </span>print_r($v);</p><p>}</p><p>获取搜索匹配数量</p><p>出于性能考虑,搜索结果的匹配数量均被设计为估算值,并非准确值。</p><p>1. 索引库内的数据总数</p><p>这个数量是真实准确的,并非估算,获取总量有以下两种做法,至于喜欢用哪种您自己决定。</p><p>调用方法 XSSearch::getDbTotal</p><p>读取魔术属性 XSSearch::dbTotal,内部也是调用上述方法</p><p>$total = $search->dbTotal;</p><p>$total = $search->getDbTotal();</p><p>2. 最近一次搜索的匹配数</p><p>通过 XSSearch::getLastCount 或 XSSearch::lastCount 可以快速获取到最近一次调用 XSSearch::search 进行搜索时得到的匹配数量。</p><p>除非您对搜索结果完全不关心,否则强烈建议用这种方法获取匹配数目以减少系统开销。</p><p>// 假设曾经有一次 search 调用</p><p>$docs = $search->setQuery('测试')->setLimit(5)->search();</p><p></p><p>// 必须在 search() 之后调用</p><p>$count = $search->lastCount;</p><p>$count = $search->getLastCount();</p><p>3. 直接获取搜索匹配数</p><p>通过 XSSearch::count 调用可以直接获取搜索的匹配数量,该方法和 XSSearch::search 类似,在调用前可以做一系列的搜索查询语句构建,也可以直接接受查询语句做参数。</p><p>返回值是一个整型数字,是估算值。</p><p>// 先设置 Query 再获取数量</p><p>$count = $search->setQuery('神雕侠侣 -电视剧')->count();</p><p></p><p>// 直接把 Query 语句传入</p><p>$count = $search->count('杭州 西湖');</p><p>获取热门搜索词<br/></p><p>在您的搜索功能进行一段时间后,系统会记录并分析所有的搜索词汇, 提供热门搜索词列表以辅助网站运营、引导用户搜索。</p><p>热门搜索词使用 XSSearch::getHotQuery 方法,返回值是以搜索词为键、 搜索指数为值的关联数组。接受 2 个可选参数如下:<br/></p><p>$limit 整数值,设置要返回的词数量上限,默认为 6,最大值为 50</p><p>$type 指定排序类型,默认为 total(总量),可选值还有:lastnum(上周) 和 currnum(本周)</p><p>$words = $search->getHotQuery(); // 获取前 6 个总热门搜索词</p><p>$words = $search->getHotQuery(10, 'lastnum'); // 获取前 10 个上周热门词</p><p>有关热门搜索的深度挖掘</p><p>搜索日志也是一个完整的索引库,可以进行更深入的分析。由于涉及的知识和基础较为复杂, 这块内容这儿暂时略过。</p><p>获取相关搜索词<br/></p><p>相关搜索通常是作为当前搜索词的搜索建议出现在搜索结果的下方,引导用户发现其它 更具体、更符合要求的关键词。</p><p>相关搜索词使用 XSSearch::getRelatedQuery 方法,返回值是搜索词组成的数组。 接受 2 个可选参数如下:</p><p>$query 搜索语句,返回跟这个搜索语句相关的搜索词,默认为 NULL 使用最近那次 setQuery 的语句</p><p>$limit 整数值,设置要返回的词数量上限,默认为 6,最大值为 20</p><p>$search->setQuery('西湖');</p><p>// 获取前 6 个和默认搜索语句 "西湖" 相关搜索词</p><p>$words = $search->getRelatedQuery();</p><p></p><p>// 获取 10 个和 "杭州" 相关的搜索词</p><p>$words = $search->getRelatedQuery('杭州', 10);</p><p>搜索建议和纠错</p><p>这项功能也是建立在搜索日志的基础上。</p><p>1. 拼写纠错</p><p>对于英文,由于打字速度过快或各种原因都很容易造成一两个字母出错。对于中文来说,古代就动不动 出现同音"通假字",绝大多数现代人也使用拼音输入法,加上方言口音,乱用同音字现象非常普遍。</p><p>所以系统在综合分析索引库内的词汇、用户搜索日志基础上建立了一个庞大的纠错体系,支持英文拼写 纠错、中文同音字纠错、拼音转换等。</p><p>使用这些功能都非常简单,直接调用 XSSearch::getCorrectedQuery 即可,该方法接受搜索语句 作为参数,如省略参数则直接使用最近一次 setQuery 的语句,返回值是修正词汇组成的数组,若 没有更合适的修正方案则返回空数组。</p><p>// 假设在本意是在 demo 项目中搜索 "测试",但不小心打成了 "侧试"</p><p>$search->setQuery('侧试');</p><p>$docs = $search->search();</p><p></p><p>// 由于拼写错误,这种情况返回的数据量可能极少甚至没有,因此调用下面方法试图进行修正</p><p>$corrected = $search->getCorrectedQuery();</p><p>if (count($corrected) !== 0)</p><p>{</p><p> // 有纠错建议,列出来看看;此情况就会得到 "测试" 这一建议</p><p> echo "您是不是要找:\n";</p><p> foreach ($corrected as $word)</p><p> {</p><p> echo $word . "\n";</p><p> }</p><p>}</p><p></p><p>/**</p><p>* 以下拼写示例则简化,并直接传入 Query 语句进行测试</p><p>* 您也可以例句用 `util/Quest.php demo --correct <word>` 进行测试</p><p></p><p>$search->getCorrectedQuery('cs'); // 通过声母缩写得到建议: "测试"</p><p>$search->getCorrectedQuery('ceshi'); // 通过全拼缩写得到建议: "测试"</p><p>$search->getCorrectedQuery('yunsearch'); // 通过拼写纠错得到: xunsearch</p><p>$search->getCorrectedQuery('xunseach 侧试'); // 混合纠错得到: xunsearch测试</p><p>Tip: 建议在搜索结果数量过少或没有时再尝试进行拼写纠错,而不是每次搜索都进行。</p><p>2. 搜索建议</p><p>搜索建议是指类似百度那样,当用户在搜索框输入少量的字、拼音、声母时提示用户一些相关的 热门关键词列表下拉框供用户选择。</p><p>这样做非常有利于节省用户的打字时间、提升用户体验。</p><p>我们通过 XSSearch::getExpandedQuery 来读取展开的搜索词,该方法返回展开的搜索词组成的 数组,如果没有任何可用词则返回空数组。接受 2 个参数:</p><p>$query 要展开的搜索词,返回结果是以这个搜索词为前缀、拼音前缀展开,此为必要参数</p><p>$limit 整数值,设置要返回的词数量上限,默认为 10,最大值为 20</p><p>/**</p><p>* 以下例子也可以用 `util/Quest.php demo --suggest <word>` 进行测试</p><p>$search->getExpandedQuery('x'); // 返回:项目, xunsearch, 行为, 项目测试</p><p>$search->getExpandedQuery('xm'); // 返回:项目, 项目测试</p><p>$search->getExpandedQuery('项'); // 返回:项目, 项目测试</p><p>$search->getExpandedQuery('项目'); // 返回:项目测试</p><p>按字段值分面搜索</p><p>分面搜索在英文中通常表述为 Facets Search,被检索的数据通具有多维度属性。 例如一本书包含主题、作者、年代等,而分面搜索是指通过事物的这些属性不断筛选、 过滤搜索结果的方法,可以将分面搜索看成搜索和浏览的结合。</p><p>如果您还是不清楚它的概念,敬请参阅这篇文章。</p><p>1. 适用情况</p><p>在 xunsearch 中,分面搜索是按照字段的值来实现的,为了结合条件做筛选搜索, 支持分面的字段需要进行索引,而它的分词方式最好必须是 full 即整值索引。</p><p>2. 用法详细示范</p><p>以论坛文章搜索为例,每篇文章均属于不同版块(字段为 fid)、不同的发表年份 (字段为 year),我们需要在搜索结果中按年份、版块显示匹配的文章数。</p><p>那么在构建搜索语句时使用 XSSearch::setFacets 方法来指定需要分面的字段, 该方法接受两个参数,第一参数为要分面的字段名称(多个字段请用数组作参数), 第二参数是可选的布尔类型,true 表示需要准确统计,默认 false 则为估算。</p><p>执行搜索之后再调用 XSSearch::getFacets 方法可取回分面搜索结果。</p><p>// 在搜索时加入分面设置</p><p>$docs = $search->setQuery('关键词')->setFacets(array('fid', 'year'))->search();</p><p></p><p>// 读取分面结果</p><p>$fid_counts = $search->getFacets('fid'); // 返回数组,以 fid 为键,匹配数量为值</p><p>$year_counts = $search->getFacets('year'); // 返回数组,以 year 为键,匹配数量为值</p><p></p><p>// 遍历 $fid_counts, $year_counts 变量即可得到各自筛选条件下的匹配数量</p><p>foreach ($fid_counts as $fid => $count)</p><p>{</p><p> echo "其中版块ID为 $fid 的匹配数为: $count\n";</p><p>}</p><p></p><p>// ...</p><p>// 通常可以循环生成新的搜索链接,在搜索链接中加入字段搜索条件即可</p><p>// 然后像往常一样使用 $docs 显示文档<br/></p><p>//搜索结果高亮显示</p><p>$docs=$search->setQuery('php')->setLimit(5)->search();</p><p>foreach($docs as $v){</p><p><span > </span>$subject=$search->highlight($v->subject);</p><p><span > </span>$message=$search->highlight($v->message);</p><p><span > </span>echo $v->rank().'.【'.$v->pid.'】'.$subject."[".$v->percent().'%]-';</p><p><span > </span>echo date("Y-m-d",$v->chrono)."<br>".$message."<br>";</p><p>}<span > </span></p><p>echo $count = $search->count('测试');</p><p>$words = $search->getHotQuery(); // 获取前 6 个总热门搜索词</p><p>print_r($words);</p><p>$words = $search->getRelatedQuery();</p><p>print_r($words);</p>