Sphinx Mulit-Level 随机排序
Sphinx Mulit-Level Sort with Randomize
这是我对 Sphinx Sort 的挑战,我有供应商支付溢价安置和那些不支付的供应商:
我已经下了一个 multi-level 订单,其中包括 PaidVendorStatus
,它是 0 或 1,如:
order by PaidVendorStatus,Weight()
所以本质上我最终得到了多个排序组:
- PaidVendorStatus=1,权重 1
- .....
- PaidVendorStatus=1,权重 N
- PaidVendorStatus=0,权重 1
- ...
- PaidVendorStatus=0, WeightN
问题是我有三个目标:
- 在任何给定的排序组中随机排列每个供应商的优先级
- 让每个供应商的 'odds' 被随机分配到最高位置,无论他们在组中返回了多少记录(因此,如果供应商 A 有 50 个结果,供应商 B 有 2 个结果,他们仍然有 50 % 被随机分配给任何给定地点的几率)
- 理想情况下,在任何给定搜索中保持相同的结果顺序(这样,如果用户再次搜索,将显示相同的顺序
我尝试过各种解决方案:
Select CRC32(Vendor) as RANDOM...Order by PaidVendorStatus,Weight(),RANDOM
解决了 2
和 3
除了由于 CRC32
的性质总是把同一个供应商放在第一位(第二,第三等)所以本质上没有解决根本问题。
我尝试在我的 Sphinx Configuration
中制作一个 sphinx sql_attr_string
,这是一个 concatenation
的供应商和记录标题 (Select... concat(Vendor,Title) as RANDOMIZER
..)` 然后用它来随机化
Select CRC32(RANDOMIZER) as RANDOM...
这解决了 1
和 3
,因为现在 Title
字段被抛出在随机化错误中,因此同一供应商并不总是获得第一个账单。但是,它在 2
处失败了,因为本质上我只是按标题排序,因此有两个结果的供应商 B 现在被排在第一位的变化非常小。
在理想的世界里,我自然可以这样点菜;
Order by PaidVendorStatus,Weight(),RAND(Vendor)
但这是不可能的。
对此有任何想法表示赞赏。顺便说一句,我按照 Barry Hunter
的建议 this thread on UDF 检查了一下,但除非我完全不理解(可能),否则它似乎不是解决这个问题的方法。
好吧,一个想法是:
SELECT * FROM (
SELECT *,uniqueserial(vendor_id) AS sorter FROM index WHERE MATCH(...)
ORDER BY PaidVendorStatus DESC ,Weight() DESC LIMIT 1000
) ORDER BY sorter DESC, WEIGHT() DESC:
这利用带有 pysudeo 子查询的 SPhixnes 'multiple sort' 函数。
这很有效,因为内部查询首先按 PaidVendor 排序,因此它们的项目是第一位的。这会影响调用 unqique serial 的 ordr。
这并不是真正的 'randomising' 结果,似乎您只是随机化它们以混淆供应商(因此单个供应商不会支配结果。Uniqueserial 由 'spreading' 特定供应商提供结果- 结果将倾向于在供应商之间循环。
这很棘手,因为它利用了一个相对未记录的 sphinx 功能 - 子查询。
有关 UDF,请参阅 http://svn.geograph.org.uk/svn/modules/trunk/sphinx/
仍然没有您的偏向随机答案(如 2.)
但我想起了另一个对 3 有帮助的功能。- 可以为随机数提供特定的种子。通常随机生成器是从当前时间开始播种的,它给出不断变化的值,但使用特定的种子。
然而,种子是一个数字,因此需要一个可预测但不断变化的数字。可以CRC查询吗?
... sphinx 不支持选项中的表达式,因此必须计算应用程序中的哈希值。
<?php
$query = $db->Quote($_GET['q']);
$crc = crc32($query);
$sql = "SELECT id,IDIV(WEIGHT(),100) as i,RAND() as r FROM index WHERE MATCH($query)
ORDER BY PaidVendorStatus DESC,i DESC,r ASC OPTION random_seed=$crc";
如果希望结果缓慢演变,请添加当前日期,这样每一天都是一个新的选择...
$crc = crc32($query.date('Ymd'));
这是我对 Sphinx Sort 的挑战,我有供应商支付溢价安置和那些不支付的供应商:
我已经下了一个 multi-level 订单,其中包括 PaidVendorStatus
,它是 0 或 1,如:
order by PaidVendorStatus,Weight()
所以本质上我最终得到了多个排序组:
- PaidVendorStatus=1,权重 1
- .....
- PaidVendorStatus=1,权重 N
- PaidVendorStatus=0,权重 1
- ...
- PaidVendorStatus=0, WeightN
问题是我有三个目标:
- 在任何给定的排序组中随机排列每个供应商的优先级
- 让每个供应商的 'odds' 被随机分配到最高位置,无论他们在组中返回了多少记录(因此,如果供应商 A 有 50 个结果,供应商 B 有 2 个结果,他们仍然有 50 % 被随机分配给任何给定地点的几率)
- 理想情况下,在任何给定搜索中保持相同的结果顺序(这样,如果用户再次搜索,将显示相同的顺序
我尝试过各种解决方案:
Select CRC32(Vendor) as RANDOM...Order by PaidVendorStatus,Weight(),RANDOM
解决了 2
和 3
除了由于 CRC32
的性质总是把同一个供应商放在第一位(第二,第三等)所以本质上没有解决根本问题。
我尝试在我的 Sphinx Configuration
中制作一个 sphinx sql_attr_string
,这是一个 concatenation
的供应商和记录标题 (Select... concat(Vendor,Title) as RANDOMIZER
..)` 然后用它来随机化
Select CRC32(RANDOMIZER) as RANDOM...
这解决了 1
和 3
,因为现在 Title
字段被抛出在随机化错误中,因此同一供应商并不总是获得第一个账单。但是,它在 2
处失败了,因为本质上我只是按标题排序,因此有两个结果的供应商 B 现在被排在第一位的变化非常小。
在理想的世界里,我自然可以这样点菜;
Order by PaidVendorStatus,Weight(),RAND(Vendor)
但这是不可能的。
对此有任何想法表示赞赏。顺便说一句,我按照 Barry Hunter
的建议 this thread on UDF 检查了一下,但除非我完全不理解(可能),否则它似乎不是解决这个问题的方法。
好吧,一个想法是:
SELECT * FROM (
SELECT *,uniqueserial(vendor_id) AS sorter FROM index WHERE MATCH(...)
ORDER BY PaidVendorStatus DESC ,Weight() DESC LIMIT 1000
) ORDER BY sorter DESC, WEIGHT() DESC:
这利用带有 pysudeo 子查询的 SPhixnes 'multiple sort' 函数。
这很有效,因为内部查询首先按 PaidVendor 排序,因此它们的项目是第一位的。这会影响调用 unqique serial 的 ordr。
这并不是真正的 'randomising' 结果,似乎您只是随机化它们以混淆供应商(因此单个供应商不会支配结果。Uniqueserial 由 'spreading' 特定供应商提供结果- 结果将倾向于在供应商之间循环。
这很棘手,因为它利用了一个相对未记录的 sphinx 功能 - 子查询。
有关 UDF,请参阅 http://svn.geograph.org.uk/svn/modules/trunk/sphinx/
仍然没有您的偏向随机答案(如 2.)
但我想起了另一个对 3 有帮助的功能。- 可以为随机数提供特定的种子。通常随机生成器是从当前时间开始播种的,它给出不断变化的值,但使用特定的种子。
然而,种子是一个数字,因此需要一个可预测但不断变化的数字。可以CRC查询吗?
... sphinx 不支持选项中的表达式,因此必须计算应用程序中的哈希值。
<?php
$query = $db->Quote($_GET['q']);
$crc = crc32($query);
$sql = "SELECT id,IDIV(WEIGHT(),100) as i,RAND() as r FROM index WHERE MATCH($query)
ORDER BY PaidVendorStatus DESC,i DESC,r ASC OPTION random_seed=$crc";
如果希望结果缓慢演变,请添加当前日期,这样每一天都是一个新的选择...
$crc = crc32($query.date('Ymd'));