2012-10-12 12 views
1

在問這個問題之前,理解我實際上在做什麼很重要。有沒有更好的方法從Sphinx/MySQL一次從兩張表中獲取數據?

與我實現的功能的最佳對比是Facebook的搜索功能。當你開始輸入一個下拉列表時出現各種搜索結果。在頂部,你會發現你的朋友的名字匹配你的搜索,然後匹配其他人,然後頁面,事件等。

我的情況是類似的,但我只想搜索兩件事情。用戶和文檔(在下面的代碼中命名爲漣漪)。

我有這個工作正常。當我在我的情況下通過此功能的邏輯來討論時,請耐心等待:

  1. 用戶專注於搜索輸入。
  2. Ajax請求檢索已登錄的用戶的朋友/跟蹤/跟隨並緩存它們的客戶端側(這僅發生第一次用戶論點集中的搜索輸入)
  3. 當用戶類型,高度優化函數執行正則表達式針對用戶名的陣列,並建立一個自動完成列表完成與造型等...
  4. 同時和每個按鍵一個Ajax請求被激發到下面的腳本,其執行以下操作

    • 分別執行兩個獅身人面像搜索兩個單獨的索引。一個收集用戶標識,另一個收集文檔標識(rippleid)
    • 用戶查詢的結果是通過檢查在ajax請求中發送的用戶標識數組來循環的,以避免重複初始化期間已經顯示的用戶高速朋友/追隨者檢查。
    • 接下來我們查詢實際的數據庫以獲取剩餘的用戶ID的
    • 然後重複同樣的過程,但這個時候的文件(漣漪)的用戶數據

最後任何返回的結果附加到自動完成列表。

這是執行sphinx查找並從數據庫獲取數據的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 ));

}

你可能會問,爲什麼我們正在做的初始朋友查找並不僅僅是使用獅身人面像的一切。那麼通過實施上面的方法。用戶在打字時會得到即時的反饋,因爲有一些朋友存儲在客戶端,儘管獅身人面像的速度非常快,但由於http請求,不可避免地會出現一些滯後現象。在實踐中,它的工作原理非常巧妙,它似乎也是Facebook使用的方法。

此外,還有很多javascript代碼可以防止不必要的查找,返回的數據被添加到緩存堆等等,以便將來的搜索不需要打到sphinx/db等...

現在終於到我的實際問題....

這當前的服務器端功能困擾了我很多。目前,Sphinx正在執行兩項搜索,MySQL正在執行兩項搜索。我怎麼可能將所有這些整理成一個獅身人面像查詢和一個MySQL查詢?有什麼辦法嗎? (請記住,文檔和用戶可能共享相同的PK ID,因爲它們在MySQL中的兩個完全不同的表上,並且分佈在兩個單獨的索引中(當前)。或者有什麼方法可以將兩個MySQL查詢合併在一起,使它們比兩個單獨的選擇更有效率?

或者...由於查詢的簡單性,我最好保持它們與上面分開嗎? (都是索引主鍵查詢)

我想我要求的是任何建議/建議。

任何評論都是非常受歡迎的。

回答

1

你不能真正逃脫沒有兩個MySQL查詢。那麼你可以通過將它們合併成一個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 

這給你一個假的關鍵,並確定結果來自哪一個表中的屬性。您可以使用它來獲取它來自的原始表。 (還有很多其他的方法可以做同樣的事情)

這可以讓你運行一個查詢,可以得到組合的結果。

......但不相信它的一個好主意。因爲如果結果不對稱,您可能會錯過結果。假設一個表格有20個匹配結果,另一個表格有10個匹配結果。假設你展示前10名的結果,現在只有極限,第二張表的結果可能會隱藏在第一張表的下方(extream例子,實際上,希望他們混合在一起)。兩個獨立的查詢,可以讓你保證,從每個表中獲得一些結果。

......等等。堅持你得到的。沒關係。

+0

非常感謝Barry ......我想我只是擔心我所做的一切會違揹我的關係數據庫風格本能。乾杯:) – gordyr

+0

實際上,可能會有一點細化。讓客戶端發出TWO Ajax請求。用戶和漣漪各一次。所以你有兩個獨立的腳本。原因是允許兩個查詢並行運行。雖然好處很小,不值得。幾乎可以肯定,不成熟的優化 – barryhunter

+0

有趣的想法...我會着迷於它。謝謝! – gordyr

0

您可以在Sphinx中存儲和檢索有關用戶和文檔的所有數據,因此不需要MySQL。

使用獅身人面像QL沒有API(更好,更容易得到的東西做 - >http://sphinxsearch.com/docs/current.html#sphinxql-reference

注意:不要忘記設置要作爲從sphinx.conf中源sql_field_string檢索數據後面的所有文本字段

相關問題