[英]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.