在問這個問題之前,理解我實際上在做什麼很重要。有沒有更好的方法從Sphinx/MySQL一次從兩張表中獲取數據?
與我實現的功能的最佳對比是Facebook的搜索功能。當你開始輸入一個下拉列表時出現各種搜索結果。在頂部,你會發現你的朋友的名字匹配你的搜索,然後匹配其他人,然後頁面,事件等。
我的情況是類似的,但我只想搜索兩件事情。用戶和文檔(在下面的代碼中命名爲漣漪)。
我有這個工作正常。當我在我的情況下通過此功能的邏輯來討論時,請耐心等待:
- 用戶專注於搜索輸入。
- Ajax請求檢索已登錄的用戶的朋友/跟蹤/跟隨並緩存它們的客戶端側(這僅發生第一次用戶論點集中的搜索輸入)
- 當用戶類型,高度優化函數執行正則表達式針對用戶名的陣列,並建立一個自動完成列表完成與造型等...
同時和每個按鍵一個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查詢合併在一起,使它們比兩個單獨的選擇更有效率?
或者...由於查詢的簡單性,我最好保持它們與上面分開嗎? (都是索引主鍵查詢)
我想我要求的是任何建議/建議。
任何評論都是非常受歡迎的。
非常感謝Barry ......我想我只是擔心我所做的一切會違揹我的關係數據庫風格本能。乾杯:) – gordyr
實際上,可能會有一點細化。讓客戶端發出TWO Ajax請求。用戶和漣漪各一次。所以你有兩個獨立的腳本。原因是允許兩個查詢並行運行。雖然好處很小,不值得。幾乎可以肯定,不成熟的優化 – barryhunter
有趣的想法...我會着迷於它。謝謝! – gordyr