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

Php 使用Sphinx/MySQL是否有更好的方法同时从两个表中获取数据?,php,mysql,sphinx,Php,Mysql,Sphinx,在问这个问题之前,了解我实际上在做什么是很重要的 与我正在实现的功能最好的比较是Facebook的搜索功能。开始键入时,会出现一个下拉列表,其中包含各种搜索结果。在顶部,您将找到与您的搜索匹配的朋友,然后是其他匹配的人,然后是页面、事件等 我的情况是相似的,但我只想寻找两件事。用户和文档(在下面的代码中命名为ripples) 我的这个很好用。请耐心听我讲述我的案例中此功能的逻辑: 用户关注搜索输入 Ajax请求检索登录用户的朋友/追随者/追随者,并将其缓存到客户端(这仅在用户第一次关注搜索输入时

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

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

我的情况是相似的,但我只想寻找两件事。用户和文档(在下面的代码中命名为ripples)

我的这个很好用。请耐心听我讲述我的案例中此功能的逻辑:

  • 用户关注搜索输入
  • Ajax请求检索登录用户的朋友/追随者/追随者,并将其缓存到客户端(这仅在用户第一次关注搜索输入时发生)
  • 当用户输入时,一个高度优化的函数对用户名数组执行一个正则表达式,并构建一个自动完成列表,其中包含头像等
  • 同时,对于每个按键,都会向下面的脚本触发一个ajax请求,该脚本执行以下操作

    • 在两个单独的索引上执行两个单独的Sphinx搜索。一个用于收集用户id,另一个用于收集文档id(rippleid)
    • 用户查询的结果通过检查ajax请求中发送的用户id数组来循环,以避免重复在初始高速好友/追随者检查期间已经显示的用户
    • 接下来,我们查询实际数据库以获取剩余用户ID的用户数据
    • 然后重复相同的过程,但这一次用于文档(涟漪)
  • 最后,所有返回的结果都会附加到自动完成列表中

    这是执行sphinx查找并从数据库获取数据的PHP函数示例

    }

    你可能会问,为什么我们要做最初的朋友查找,而不仅仅是使用斯芬克斯。通过实施上述方法,可以很好地解决这个问题。由于客户端存储了朋友数组,用户在键入时会得到即时反馈,而尽管sphinx的速度非常快,但由于http请求,不可避免地会出现一些延迟。在实践中,它工作得非常出色,顺便说一句,它似乎也是facebook使用的方法

    还有很多javascript代码防止不必要的查找,返回的数据被添加到缓存堆等,以便将来的搜索不需要点击sphinx/db等

    现在终于开始我的实际问题了……

    目前的服务器端功能让我很烦恼。现在有两个搜索由Sphinx执行,两个搜索由MySQL执行。我怎样才能将所有这些整理成一个sphinx查询和一个MySQL查询?有什么办法吗?(请记住,文档和用户可能共享相同的PK ID,因为它们位于MySQL中两个完全不同的表上,并且(目前)分布在两个单独的索引中)。或者,有没有什么方法可以将两个MySQL查询组合起来,使它们比使用两个单独的SELECT更有效

    或者。。。由于查询的简单性,我是否最好像上面那样将它们分开?(两者都是索引主键查询)

    我想我需要的是任何建议


    欢迎任何评论。

    如果没有两个MySQL查询,你真的无法逃脱。好吧,你可以,通过jsut将它们结合成一个,结合起来。或者通过创建一个新的组合“表”(一个视图或一个物化视图),但真的不认为这是值得的。两个查询是非常好的——正如您所说,它们已被索引

    通过创建新的组合索引,可以使用一个sphinx索引(以及一个搜索查询)。因为您说您的密钥不是唯一的,所以必须创建一个新的合成密钥

    例如

    这将为您提供一个伪键和一个属性来标识结果来自哪个表。您可以使用它来获取它来自的原始表。(做同样的事情还有很多其他方法)

    这允许您运行一个查询,可以得到组合结果

    。。。但我不相信这是个好主意。因为如果结果是不对称的,您可能会错过结果。假设一个表有20个匹配结果,另一个表有10个匹配结果。假设您显示前10个结果,现在由于限制,第二个表的结果很可能隐藏在第一个表的下面(extream示例,实际上,希望它们混合在一起)。两个独立的查询允许您保证从每个表中获得一些结果


    。。。所以在那之后。坚持你所拥有的。很好

    如果没有两个MySQL查询,你真的无法逃脱。好吧,你可以,通过jsut将它们结合成一个,结合起来。或者通过创建一个新的组合“表”(一个视图或一个物化视图),但真的不认为这是值得的。两个查询是非常好的——正如您所说,它们已被索引

    通过创建新的组合索引,可以使用一个sphinx索引(以及一个搜索查询)。因为您说您的密钥不是唯一的,所以必须创建一个新的合成密钥

    例如

    这将为您提供一个伪键和一个属性来标识结果来自哪个表。您可以使用它来获取它来自的原始表。(做同样的事情还有很多其他方法)

    这允许您运行一个查询,可以得到组合结果

    。。。但我不相信这是个好主意。因为如果结果是不对称的,您可能会错过结果。假设一个表有20个匹配结果,另一个表有10个匹配结果。假设您显示前10个结果,现在由于限制,第二个表中的结果很可能被隐藏 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
                            ));
    
    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