在问这个问题之前,重要的是要了解我实际上在做什么。
与我正在实施的功能的最佳比较是 Facebook 的搜索功能。当您开始键入时,会出现一个带有各种搜索结果的下拉列表。在顶部,您会找到名字与您的搜索匹配的朋友,然后是匹配的其他人,然后是页面、事件等。
我的情况类似,但我只想搜索两件事。用户和文档(在下面的代码中命名为涟漪)。
我有这个工作正常。在我讨论此功能的逻辑时,请多多包涵:
- 用户关注搜索输入。
- Ajax 请求检索登录的用户朋友/关注者/关注者并在客户端缓存它们(这只发生在用户第一次关注搜索输入时)
- 当用户键入时,高度优化的函数对用户名数组执行正则表达式,并构建一个包含头像等的自动完成列表......
同时,每次按键都会向下面的脚本触发一个 ajax 请求,该脚本执行以下操作:
- 对两个单独的索引执行两个单独的Sphinx搜索。一个收集用户 ID,另一个收集文档 ID(rippleid)
- 用户查询的结果通过检查在 ajax 请求中发送的用户 ID 数组进行循环,以避免重复在初始高速朋友/关注者检查期间已经显示的用户。
- 接下来我们查询实际数据库以获取剩余用户 ID 的用户数据
- 然后重复相同的过程,但这次是针对文档(涟漪)
最后,任何返回的结果都会附加到自动完成列表中。
这是执行 sphinx 查找并从数据库中获取数据的 PHP 函数示例。
公共功能搜索()
{
$this->disableLayout();
$request = 新请求();
$params = $request->getParams(GET);
//Perform sphinx textsearch
include('/usr/local/lib/php/sphinxapi.php');
$sphinx = new \SphinxClient();
$sphinx->setMatchMode(SPH_MATCH_ANY);
$sphinx->SetLimits(0, 4);
$mysqlconn = mysql_connect("127.0.0.1:9306") or die ("Couldn't connect to MySQL.");
$users = $sphinx->Query($params['data']['q'], "users");
$ripples = $sphinx->Query($params['data']['q'], "ripples");
/*
*USERS
*/
//Loop through users and only collect ID's that are not already present
if (!empty($users["matches"])) {
$ids = "";
foreach($users['matches'] as $id => $data) {
if($ids > ""){
$ids .= ",";
}
if(!isset($params['data']['e'][$id])){
$ids .= $id;
}
}
//If there any any remaining ID's collect the data from the database and return as JSON
if(!empty($ids)){
$userdataquery = "select users.userid, users.firstname, users.lastname
from tellycards_user_data users
where userid IN($ids)
";
$query = new Query($userdataquery);
$usersoutput = $query->fetchAll();
}
}
/*
*RIPPLES
*/
//Loop through ripples and collect ID's
if (!empty($ripples["matches"])) {
$rippleids = "";
foreach($ripples['matches'] as $id => $data) {
if($rippleids > ""){
$rippleids .= ",";
}
$rippleids .= $id;
}
//If there any any remaining ID's collect the data from the database and return as JSON
if(!empty($rippleids)){
$rippledataquery = "select ripples.id, ripples.name, ripples.screenshot
from tellycards_ripples ripples
where id IN($rippleids)
";
$query = new Query($rippledataquery);
$ripplesoutput = $query->fetchAll();
}
}
header('Content-type: text/json');
echo json_encode(array(
'users' => (!empty($usersoutput)) ? $usersoutput : null,
'ripples' => (!empty($ripplesoutput)) ? $ripplesoutput : null
));
}
您可能会问为什么我们要进行初始朋友查找,而不仅仅是对所有内容都使用 sphinx。那么通过实现上面的方法。由于客户端存储了好友数组,用户在打字时会得到即时反馈,尽管 sphinx 的速度非常快,但由于 http 请求,不可避免地会出现一些延迟。在实践中,它的效果非常好,顺便说一下,它似乎也是 facebook 使用的方法。
还有很多 javascript 代码防止不必要的查找,返回的数据被添加到缓存堆等,因此未来的搜索不需要点击 sphinx/db 等......
现在终于到了我的实际问题....
这个当前的服务器端功能让我很困扰。目前,Sphinx 执行了两次搜索,MySQL 执行了两次搜索。我怎么可能将所有这些整理成一个 sphinx 查询和一个 MySQL 查询?有什么办法吗?(请记住,文档和用户可能共享相同的 PK ID,因为它们位于 MySQL 中的两个完全不同的表上,并且(当前)分布在两个单独的索引中)。或者有什么方法可以组合两个 MySQL 查询,使它们比两个单独的选择更有效?
或者...由于查询的简单性,我最好将它们分开吗?(两者都是索引主键查询)
我想我要的是任何建议/建议。
非常欢迎任何评论。