[英]Is there a better way to get data from two tables at once with Sphinx/MySQL?
在问这个问题之前,重要的是要了解我实际上在做什么。
与我正在实现的功能的最佳比较将是Facebook的搜索功能。 当您开始输入内容时,会出现一个包含各种搜索结果的下拉列表。 在顶部,您会找到名字与您的搜索相匹配的朋友,然后是与之匹配的其他人,然后是页面,事件等。
我的情况类似,但是我只想搜索两件事。 用户和文档(在下面的代码中命名为涟漪图)。
我的工作很好。 在我讨论此功能的逻辑时,请多多包涵:
同时,对于每次按键,都会向下面的脚本触发一个ajax请求,该脚本执行以下操作 :
最后,所有返回的结果都将附加到自动完成列表中。
这是PHP函数的一个示例,该函数执行狮身人面像查找并从数据库中获取数据。
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。 通过实现上面的方法就可以了。 用户输入时由于在客户端存储了朋友的数组而获得了即时反馈,尽管狮身人面像的速度惊人,但由于http请求,不可避免地会有一些滞后。 在实践中,它工作得非常好,顺便说一句,它似乎也是Facebook使用的方法。
还有很多JavaScript代码可防止不必要的查找,将返回的数据添加到缓存堆等中,以便将来的搜索不需要点击sphinx / db等。
现在终于到了我的实际问题。
当前的服务器端功能使我非常困扰。 目前,Sphinx执行了两次搜索,MySQL执行了两次搜索。 如何将所有这些整理为一个狮身人面像查询和一个MySQL查询? 有什么办法吗? (请记住,文档和用户可能共享相同的PK ID,因为它们位于MySQL的两个完全不同的表中,并且(当前)分布在两个单独的索引中)。 还是有什么办法可以将两个MySQL查询组合在一起,使其比拥有两个单独的选择更有效率?
或者作为替代...由于查询的简单性,我是否最好如上所述将它们分开? (均为索引主键查询)
我想我要的是任何建议/建议。
任何评论都非常欢迎。
没有两个MySQL查询真的无法摆脱。 好的,您可以通过JSUT将它们与UNION合并为一个。 或通过创建一个新的组合“表”(一个视图或一个实体化视图)-但实际上并不认为这样做值得。 两个查询都很好-正如您所说的,它们已建立索引。
您可以使用一个狮身人面像索引(因此可以使用一个搜索查询)-通过创建新的组合索引。 因为您说密钥不是唯一的,所以必须创建一个新的合成密钥。
例如...
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
这为您提供了一个伪造的key,以及一个用于标识结果来自哪个表的属性。 您可以使用它来获取它来自的原始表。 (有许多其他方式可以做相同的事情)
这使您可以运行一个查询,可以获得合并结果。
...但是没有说服它是一个好主意。 因为如果结果不对称,您可能会错过结果。 假设一张表有20个匹配结果,另一张表有10个匹配结果。 假设您显示的是前10个结果,现在是极限,因为第二个表的结果很可能隐藏在第一个表的下方(极端示例,实际上,希望它们混合在一起)。 两个单独的查询使您可以保证从每个表中获得一些结果。
...所以毕竟。 坚持你所得到的。 没关系。
您可以在Sphinx中存储和检索有关用户和文档的所有数据,因此不需要MySQL。
使用Sphinx QL而不是API(更好,更轻松地完成工作-> http://sphinxsearch.com/docs/current.html#sphinxql-reference )
注意:不要忘记将所有要从中检索数据的文本字段设置为sphinx.conf源中的sql_field_string
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.