在提出这个问题之前,了解我实际上在做什么很重要。
与我正在实施的功能的最佳比较将是Facebook的搜索功能。当您开始输入时,会出现包含各种搜索结果的下拉列表。在顶部,您会找到名字与您的搜索匹配的朋友,然后是其他匹配的人,然后是页面,活动等....
我的情况类似,但我只想搜索两件事。用户和文档(在下面的代码中命名为涟漪)。
我的工作正常。在我谈论这个功能的逻辑时,请耐心等待我:
同时,对于每个按键,都会向下面的脚本触发ajax请求:
最后,任何返回的结果都会附加到自动完成列表中。
这是PHP函数的一个示例,它执行sphinx查找并从数据库中获取数据。
public function search()
{
$this->disableLayout();
$request = new 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查询?有什么办法吗? (请记住,文档和用户可能在MySQL中的两个完全不同的表上共享相同的PK ID,并且(通过两个单独的索引)传播(当前)。或者有没有办法将两个MySQL查询结合起来,使它们比两个单独的选择更有效?
或者......由于查询的简单性,我最好将它们分开,如上所述? (两者都是索引主键查询)
我想我要求的是任何建议/建议。
非常欢迎任何评论。
答案 0 :(得分:1)
你真的无法逃脱没有两个MySQL查询。好吧,你可以通过jsut将它们合并为一个,与UNION合作。或者通过创建一个新的组合'表'(视图或物化视图) - 但真的不认为它值得努力。两个查询完全正常 - 正如您所说的那样。
您可以使用一个sphinx索引(因此也可以使用一个搜索查询) - 通过创建新的组合索引。因为您说您的密钥不是唯一的,所以必须创建一个新的合成密钥。
...例如
sql_query = SELECT userid*2 AS id, 1 AS table_id, firstname AS one, lastname as two FROM tellycards_user_data \
UNION \
SELECT (id*2)+1 as id, 2 AS table_id, name AS one, screenshot AS two FROM tellycards_ripples
sql_attr_unit = table_id
这为您提供了一个假密钥,以及一个用于标识结果来自哪个表的属性。您可以使用它来获取它来自的原始表。 (还有很多其他方法可以做同样的事情)
这允许您运行一个查询,可以获得组合结果。
......但不相信这是一个好主意。因为如果结果不对称,您可能会错过结果。假设一个表有20个匹配的结果,另一个表有10个匹配的结果。假设您显示前10个结果,现在因为限制,第二个表的结果,很可能隐藏在第一个表下面(extream示例,实际上,希望它们混合在一起)。两个单独的查询,允许您保证,从每个表中获取一些结果。
......毕竟那样。坚持你所得到的。没关系。
答案 1 :(得分:0)
您可以在Sphinx中存储和检索有关用户和文档的所有数据,因此不需要MySQL。
使用Sphinx QL而不是API(更好更容易完成任务 - > http://sphinxsearch.com/docs/current.html#sphinxql-reference)
注意:别忘了在sphinx.conf源代码中将所有想要检索数据的文本字段设置为sql_field_string