繁体   English   中英

使用Sphinx / MySQL是否有更好的方法一次从两个表中获取数据?

[英]Is there a better way to get data from two tables at once with Sphinx/MySQL?

在问这个问题之前,重要的是要了解我实际上在做什么。

与我正在实现的功能的最佳比较将是Facebook的搜索功能。 当您开始输入内容时,会出现一个包含各种搜索结果的下拉列表。 在顶部,您会找到名字与您的搜索相匹配的朋友,然后是与之匹配的其他人,然后是页面,事件等。

我的情况类似,但是我只想搜索两件事。 用户和文档(在下面的代码中命名为涟漪图)。

我的工作很好。 在我讨论此功能的逻辑时,请多多包涵:

  1. 用户专注于搜索输入。
  2. Ajax请求检索已登录用户的朋友/关注者/关注者并将其缓存在客户端(仅在用户首次关注搜索输入时才会发生)
  3. 当用户输入内容时,高度优化的功能会对用户名数组执行正则表达式,并构建包含头像等的自动完成列表。
  4. 同时,对于每次按键,都会向下面的脚本触发一个ajax请求,该脚本执行以下操作

    • 在两个单独的索引上执行两个单独的Sphinx搜索。 一个收集用户ID,另一个收集文档ID(rippleid)
    • 通过查询ajax请求中发送的一组用户ID来循环用户查询的结果,以避免重复在最初的高速朋友/关注者检查期间已经显示的用户。
    • 接下来,我们查询实际数据库以获取剩余用户ID的用户数据
    • 然后重复相同的过程,但是这次是文件(波纹)

最后,所有返回的结果都将附加到自动完成列表中。

这是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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM