须要对这3个字段查询。然后按照字段的命中排序。不管一个字段有多少数据,对于一个字段只要命中了就算一次,然后对应的不同字段乘以对应字段应该的权重。
比如行业命中那么权重*1,地区命中那么权重*2,职位命中那么权重*2
总权重=(行业字段命中*1)+(地区字段命中*2)+(职位命中*2)
然后按照总权重进行排序。
错误:
cl.SetSortMode(SphinxClient.SPH_SORT_EXPR, "@industry*1+@area*2+@expr*2");
SphinxResult res = cl.Query("(@industry 建材)|(@area 北京)|(@expr 经理)", "idx_test");
但是不能对字段进行数学操作,会报如下的错误:
Error: index idx_test: unknown identifier '@industry' (not an attribute, not a function)
SPH_SORT_EXPR只能操作数字。
正确:
可以使用$cl->SetRankingMode ( SPH_RANK_PROXIMITY );//设置评分模式
解决按照字段命中计算权值。
$cl->SetMatchMode ( SPH_MATCH_EXTENDED );//设置模式
$cl->SetRankingMode ( SPH_RANK_PROXIMITY );//设置评分模式
$cl->SetFieldWeights (array('industry'=>1,'area'=>2,'expr'=>2));//设置字段的权重,如果area命中,那么权重算2
$cl->SetSortMode ('SPH_SORT_EXPR','@weight');//按照权重排序
上面代码就解决了我的问题。
不过SPH_RANK_PROXIMITY 评分模式在java的api中没有,在php的api中有,我使用的是3.2.13版本的。
采用何种权值计算函数(目前)取决于查询的模式。
权值计算函数进行如下两部分主要部分:
- 词组评分,
- 统计学评分.
词组评分根据文档和查询的最长公共子串(LCS,longest common subsequence)的长度进行。因此如果文档对查询词组有一个精确匹配(即文档直接包含该词组),那么它的词组评分就取得了可能的最大值,也就是查询中词的个数。
统计学评分基于经典的BM25函数,该函数仅考虑词频。如果某词在整个数据库中很少见(即文档集上的低频词)或者在某个特定文档中被经常提及(即特定文档上的高频词),那么它就得到一个较高的权重。最终的BM25权值是一个0到1之间的浮点数。
在所有模式中,数据字段的词组评分是LCS乘以用户指定的数据字段权值。数据字段权值是整数,默认为1,且字段的权值必须不小于1。
在SPH_MATCH_BOOLEAN模式中,不做任何权重估计,每一个匹配项的权重都是1。
在SPH_MATCH_ALL和SPH_MATCH_PHRASE模式中,最终的权值是词组评分的加权和。
在SPH_MATCH_ANY模式中,于前面述两模式的基本思想类似,只是每个数据字段的权重都再加上一个匹配词数目。在那之前,带权的词组相关度被额外乘以一个足够大的数,以便确保任何一个有较大词组评分的数据字段都会使整个匹配的相关度较高,即使该数据字段的权重比较低。
在SPH_MATCH_EXTENDED模式中,最终的权值是带权的词组评分和BM25权重的和,再乘以1000并四舍五入到整数。
这个行为将来会被修改,以便使MATCH_ALL和MATCH_ANY这两个模式也能使用BM25算法。这将使词组评分相同的搜索结果片断得到改进,这在只有一个词的查询中尤其有用。
关键的思想(对于除布尔模式以外的全部模式中)是子词组的匹配越好则评分越高,精确匹配(匹配整个词组)评分最高。作者的经验是,这种基于词组相似性的评分方法可以提供比任何单纯的统计模型(比如其他搜索引擎中广泛使用的BM25)明显更高的搜索质量。