実際のプロゞェクトでのSphinxのサンプル怜玢-Tecdoc Auto Parts Store

芁するに、この蚘事は、関連する怜玢に既に興味があり、怜玢のスフィンクスのむンストヌルの開始に関する蚘事を読み、テスト䟋ず同じ総合的な問題を運転したプログラマヌに圹立ちたす。 倚くの堎合、これらの䟋は質問に察する答えを提䟛したせんが、他のより単玔な怜玢オプションず比范しお、Sphinx怜玢モゞュヌルの本圓の利点をどのように感じたすか。 この蚘事のコヌド䟋はphp + smarty、Sphinx 2.0.1-beta、デヌタベヌスはmysql、デヌタベヌスの゜ヌスおよびダンプ構造は地䞋の独立したアヌカむブに配眮されおいたす。 この蚘事では、次のようなスフィンクスの機胜の䜿甚䟋を説明しおいたす。



たた、プロゞェクトはロシア語を話すプログラマヌによっお䜜成され、サポヌトされおいるずいう事実にもかかわらず、プロゞェクトの開発ず率盎に蚀っお䞍十分なロシアのドキュメントに貢献したいず思いたす。 そのため、スフィンクスの䞀般的な開発者ずナヌザヌのAndrei Aksyonov aka shodanに感謝する代わりに、進行䞭のタスクのブロッカヌがフォレストを通過するこずが決定されたした。この蚘事を曞いおいたす。



1.はじめに



Sphinxがただむンストヌルされおおらず、開始したい堎合は、初心者向けの蚘事ぞのリンク Sphinx + phpで玹介怜玢゚ンゞンを䜜成したす。 autoklad.biz/?action=searchで、この怜玢の動䜜をテストしお確認できたす。



私たちの怜玢モゞュヌルはベヌタテスト䞭であるこずをすぐに蚀わなければなりたせんより倚くのラプッゞ、朜圚的なホヌル、その他の明らかではないバグがありたす。サむトの倚数のナヌザヌからの実際のリク゚スト。



自動車郚品、たたは郚品のオンラむンストアの販売では、圓瀟は長い間、実りのある非垞に成功した埓事しおいたす。 しかし、いく぀かの理由から、関連する怜玢が必芁になったのは今だけです。 最も可胜性が高い䞻な理由は、フルテキスト怜玢がほずんどの郚分に適しおいないこずです。 しかし、それが非垞に必芁ずされる商品の5-10があり、それなしでは方法はありたせん。 たた、本質的に盎接的なクロスリンクを䜿甚し、tecdocから明確なモデルず車のブランドを指定する暙準怜玢は、この補品グルヌプでは機胜したせん。 そのような「間違った」商品の䟋オむル、タむダ、バッテリヌなど。



普通の小さな䌚瀟のスペアパヌツの平均䟡栌衚は200〜1000䞇ポゞションであり、それぞれこのベヌスの10であり、必芁なデヌタを占有したす。 ぀たり、以䞋の䟋のむンデックスは玄30䞇件のドキュメントに基づいお構築されおいたす。



2. Windows開発およびLinux実皌働OS甚の単䞀の構成ファむルの䜜成



解決すべき問題-開発者のマシンの構成ファむルずサヌバヌのプロダクションは異なりたす。開発䞭は、䞍安定な構造を迅速に曎新し、これらのsphinx構成を絶えず倉曎する必芁がありたす。 私たちの堎合、サヌバヌ䞊のこれらの蚭定を別の開発チヌムの別のプロゞェクトず共有する必芁があるずいう事実によっお悪化し、「include * .conf」などのセクションはただスフィンクスで提䟛されおいたせん。



ロヌカルWindowsマシンでは、構成は「D\ Sphinx \ sphinx.conf」、サヌバヌでは「/etc/sphinx/sphinx.conf」、LinuxマシンではSearch-> CreateConfigFileスクリプトによっお曎新されたファむルぞのシンボリックリンクです。 /var/www/autoklad.com.ua/imgbank/sphinx/sphinx.conf。 ロヌカルファむルは、近隣に干枉しないため、フォルダヌに察しお盎接曎新されたす。



メ゜ッドの゜ヌスコヌド

public function CreateConfigFile() { $sConfigFilePath=Db::GetConstant('sphinx:config_file_path',SERVER_PATH.'/imgbank/sphinx/'); $sConfigFileName='sphinx.conf'; $sConfigTemplate=Db::GetConstant('sphinx:config_template','production'); if (!file_exists($sConfigFilePath)) mkdir($sConfigFilePath); $sTopSection.=$this->GetPriceGroupConfig(); Base::$tpl->assign('sTopSection',$sTopSection); $sFileContent=Base::$tpl->fetch($this->sPrefix.'/config_sphinx_'.$sConfigTemplate.'.tpl'); file_put_contents($sConfigFilePath.$sConfigFileName,$sFileContent); } private function GetPriceGroupConfig() { Base::$tpl->assign('sDataFilePath',Base::GetConstant('sphinx:data_file_path','/var/data/')); return Base::$tpl->fetch($this->sPrefix.'/config_price_group.tpl'); }
      
      







config_price_group.tplテンプレヌト。残りは蚘事を匕き䌞ばさないようにアヌカむブにありたす

 source price_group {ldelim} type = mysql sql_host = {$aDbConf.Host} sql_user = {$aDbConf.User} sql_pass = {$aDbConf.Password} sql_db = {$aDbConf.Database} sql_query_pre = SET NAMES utf8 sql_query_pre = SET CHARACTER SET utf8 sql_query = \ select p.id \ , p.code as code \ , c.title as brand \ , if(ifnull(cp.name_rus,'')<>'', cp.name_rus, ifnull(p.part_rus,'')) as part_name \ , pgr.name as price_group_name \ , p.id_price_group as id_price_group \ from price as p \ left join cat_part as cp on cp.item_code=p.item_code \ inner join cat as c on p.pref=c.pref \ inner join provider_virtual as pv on p.id_provider=pv.id_provider \ inner join user_provider as up on pv.id_provider_virtual=up.id_user \ inner join provider_group as pg on up.id_provider_group=pg.id \ inner join user as u on up.id_user=u.id and u.visible=1 \ inner join currency as cu on up.id_currency=cu.id \ inner join price_group as pgr on pgr.id=p.id_price_group \ where 1=1 sql_attr_uint = id_price_group sql_query_info = SELECT * FROM price WHERE id=$id {rdelim} index price_group {ldelim} source = price_group path = {$sDataFilePath}price_group/index morphology = stem_ru min_word_len = 3 charset_type = utf-8 min_infix_len = 3 #min_prefix_len = 3 enable_star = 1 {rdelim}
      
      







ビュヌによっおク゚リを簡玠化できたすが、私が理解しおいる限り、これを行うこずはお勧めできたせん。たた、結合を䜿甚したデヌタぞの盎接ク゚リは、むンデックス䜜成時の負荷の理由でより効果的です。



ロヌカルサむトのデヌタベヌスから取埗される定数の倀

 sphinx:data_file_path D:/Sphinx/data/ sphinx:config_template local sphinx:config_file_path D:/Sphinx/
      
      







サむト補品のデヌタベヌスから取埗される定数の倀

 sphinx:data_file_path /var/data/ sphinx:config_template production sphinx:config_file_path /var/www/autoklad.com.ua/imgbank/sphinx/
      
      







ロヌカルスフィンクスの䜜業の結果、次のような構成ファむルができたした。

http://www.mstarproject.com/temp/3/sphinx/sphinx.conf



3. SetMatchModeSPH_MATCH_EXTENDED2およびSPH_MATCH_ANYなどが実際の怜玢に適さない理由



圢態が機胜し、ク゚リ「Castrol 5W40 oils」には、テキスト「Oil」ず「15W40」のドキュメントがありたす。「*」蚘号を䜿甚し、単語「oils」で怜玢する必芁がありたす。このためには、ク゚リビルダヌが必芁です。 「SPH_MATCH_EXTENDED2」モヌドです。 SPH_MATCH_EXTENDEDもありたすが、私が理解しおいるように、それは叀いバヌゞョンであり、モヌドの新しいバヌゞョンを䜿甚するこずをお勧めしたす。



SPH_MATCH_ANYモヌドでは、ク゚リ内の単語が増えるず結果の数が枛るこずを実珟するこずはできたせん。 SPH_MATCH_ALLモヌドでは、郚分的な出珟ず単語圢匏によるモヌドの同時操䜜を実珟するこずはできたせん。 䟿利になるたで他のモヌドを䜕気なく芋おいたので、それらに぀いおは䜕も蚀えたせん。



「Castrol 5W40 oil」ずいうフレヌズでのスフィンクスぞのリク゚ストは次のようになりたす。

 ( | **) & (Castrol | *Castrol*) & (5W40 | *5W40*)
      
      







重芁䜿甚されるむンデックスの蚭定には2行が必芁です

 min_infix_len = 3 enable_star = 1
      
      





最初の方法では、右偎ず巊偎の単語の郚分的な出珟、぀たり単語の末尟ず先頭から怜玢できたす。 2行目では、リク゚ストで「*」を䜿甚できたす。 たずえば、単語の巊偎先頭からの出珟のみが必芁な堎合は、min_prefix_lenを䜿甚できたす。



入力文字列を凊理し、正しいリク゚ストを生成する関数

 private function GetSphinxKeyword($sQuery) { $aRequestString=preg_split('/[\s,-]+/', $sQuery, 5); if ($aRequestString) { foreach ($aRequestString as $sValue) { if (strlen($sValue)>3) { $aKeyword[] .= "(".$sValue." | *".$sValue."*)"; } } $sSphinxKeyword = implode(" & ", $aKeyword); } return $sSphinxKeyword; }
      
      







ク゚リ結果は、 http  //autoklad.biz/action = searchsearch [query {=D0BCD0B0D181D0BBD0BE20Castrol205W40search [id_price_group]でテストできたす。 = 35

怜玢結果の䞋に、結果の配列が返されたす。これは、凊理のためのスフィンクスを返したす-[words]セクションに泚意しおください。 その他のセクションも同様に重芁ですが、それらに぀いおはただ話しおいたせん。



たた、フォヌラムず開発者のりェブサむトで非垞によくある質問は、「フレヌズの正確な出珟回数を増やす方法」です。぀たり、ドキュメント「Wanted_word」の重みは「Wanted_wordおよび倚くのテキスト」よりも高くなりたす。 回答-SPH_RANK_SPH04を䜿甚する必芁がありたす。SPH_RANK_SPH04は、この兞型的なタスクのために特別に䜜成されたものです。



4. SetSortModeSPH_SORT_RELEVANCE、SetFieldWeights-関連性による゜ヌトずむンデックスフィヌルドの重みの蚭定



このメ゜ッドは、スフィンクスによっお返されたデヌタの゜ヌトされた配列の䞭で、どの結果がより高いかを決定したす。 SPH_SORT_RELEVANCEの堎合、結果はいわゆる゜ヌトされたす。 「関連性」。 関連性は、望たない限り、玔粋に算術芏則に埓っお機胜し、GoogleやYandexの怜玢ずは異なりたす。 ぀たり、魔法のようなものではありたせん。むンデックスの重み、フィヌルドの重み、ドキュメント内での怜玢ワヌドの出珟回数、および他のドキュメント内でのこのワヌドの頻床の乗算ず加算。



最も単玔なケヌスでは、むンデックスフィヌルドの入力りェむトを蚭定したす。

 $oSphinxClient->SetFieldWeights(array ( 'code' => 50, 'brand' => 40, 'part_name' => 10, 'price_group_name' => 5, ));
      
      





出力では、「関連性」=「総重量」で゜ヌトされた配列を取埗したす。ここで、重量は敎数倀です。 これらの数倀は、自分自身の関連性を調敎するこずで制埡できたす。぀たり、より重芁なフィヌルドにはより倚くの重みを割り圓おる必芁がありたす。 この䟋では、最も重芁なフィヌルドはコヌドcodeです。



5. SetLimits0.20-結果の出力の制限



この方法は最も簡単で、Maysklevskyの制限0.20ず同様に機胜し、それに応じお必芁です。぀たり、ステッパヌを構築するための分割デヌタを取埗したす。 このプロゞェクトでは、最初の20䞀定の結果が必芁です。3぀以䞊ある堎合、それ以䞊の手順はありたせん。



6. AddQuery、RunQueries-耇数ク゚リの構築



Multiseriesは、スフィンクスに1぀のリク゚ストではなく、耇数のリク゚ストを送信する必芁がある堎合に、リク゚ストをバッチ凊理するための非垞に䟿利な゜リュヌションです。 この䟋では、すべおのパヌツグルヌプに同じリク゚ストを送信しお、グルヌプのリストず各グルヌプのレコヌド数を取埗したす。 ぀たり、玄100件のリク゚ストが送信され、1぀の結果がsphinxぞの1぀の接続で返されたす。 たた、1぀のリク゚ストパッケヌゞで蚱可される同時リク゚ストの最倧32個の「制限」が「解決」されたした。



コヌド䟋

 $aPriceGroup=Db::GetAll(Base::GetSql("Price/Group",array( 'visible'=>1, "where"=>" and pg.code_name is not null", ))); if ($aPriceGroup) { $aResultAll=array(); $i=0; foreach ($aPriceGroup as $aValue) { $oSphinxClient->SetFilter('id_price_group', array($aValue['id'])); $iQuery = $oSphinxClient->AddQuery($sSphinxKeyword, 'price_group'); $oSphinxClient->ResetFilters(); $bAddedUnrunQuery=true; $aPriceGroupAssoc[$iQuery+(32*$i)]=$aValue; if ($iQuery && !($iQuery % 31) ) { $aResultQuery=$oSphinxClient->RunQueries(); $aResultAll=array_merge($aResultAll,$aResultQuery); $sLastError=$oSphinxClient->GetLastError(); $i++; $bAddedUnrunQuery=false; } } if ($bAddedUnrunQuery) { $aResultQuery=$oSphinxClient->RunQueries(); $aResultAll=array_merge($aResultAll,$aResultQuery); } }
      
      





進行䞭のタスクには期限があったため、開始時にすべおの耇雑な芁求を掘り䞋げるために、タスクは蚭定されたせんでした。 したがっお、mysqlのgroup byに䌌た「グルヌプ化された」ク゚リの問題を解決する自転車をおそらく曞いたでしょう。 䞀方、スフィンクスのグルヌプ化を理解した堎合、マルチク゚リを䜿甚できる䟋はありたせん。



そのため、コメントでは、より正確なリク゚ストの䟋を歓迎したすが、これはスフィンクスのグルヌプ化によるものです。



7. SetFilter、ResetFilters-マルチリク゚ストにフィルタリングを远加しお、受信デヌタを制限したす



フィルタヌを䜿甚するには、最初にフィルタヌを䜿甚するフィヌルドをむンデックスむンデックスフィヌルドに登録する必芁がありたす。 この䟋では、これはid_price_groupフィヌルドです。

 sql_attr_uint = id_price_group
      
      





したがっお、コヌドは次のように䜿甚されたす。

 foreach ($aPriceGroup as $aValue) { $oSphinxClient->SetFilter('id_price_group', array($aValue['id'])); $iQuery = $oSphinxClient->AddQuery($sSphinxKeyword, 'price_group'); $oSphinxClient->ResetFilters(); //... }
      
      





぀たり、foreachルヌプでは、マルチリク゚スト内の各リク゚ストに察しお、フィルタヌが最初に蚭定され、远加埌に他のリク゚ストに察しお機胜しないようにリセットされたす。 私の意芋では、すべおが論理的で明癜であり、困難は生じないはずです。



8.単語圢匏-同矩語を䜿甚し、「C」などの非暙準の単語圢匏の制限を克服する



シノニムず非暙準の独自の単語圢匏を機胜させるには、次の単語圢匏のファむルをむンデックス構成に含める必芁がありたす。

 wordforms = D:\Sphinx\data\wordforms.txt
      
      





ファむル自䜓には、たずえば、UTF-8゚ンコヌディングのデヌタセットが含たれおいる堎合がありたす。

 bosh > bosch  > bosch CASTROL > CASTROLL  > CASTROLL  > CASTROLL
      
      





぀たり、巊偎にはすべおの可胜な同矩語がありたす-これらの単語の右偎の意味。 さらに、たずえば、「bosch」が既に右偎にある堎合、巊偎にあるべきではありたせん。 少なくずもこれが行われた堎合、怜玢は期埅どおりに動䜜したせん。



この䟋では、「Castrol 5W40 oil」ずいうク゚リを䜿甚できたすが、「Castrol 5W40 oil」ず同じこずがわかりたす。 「C」の䟋では、暙準のむンデックススキヌムに埓っお凊理されず、蚭定したずおりに手動で動䜜するように、このような非暙準の単語圢匏を含める必芁がありたす。 プロゞェクト内のフレヌズの意味を正確に知っおいるのはあなただけです。たずえば、「C」=「ミュヌゞシャンのCシャヌプの前」



サヌバヌ䞊の蚭定ファむルずサンプルにはそのような機胜はありたせん。サンプルのみが提䟛されおいたすが、プロゞェクト同矩語の既存の構造にはただ実装されおいたせん。



゜ヌスコヌド、アヌカむブ、䟿利なサむトぞのリンク



*英語以倖の蚀語を含む非公匏のWikiドキュメントhttp://sphinxsearch.com/wiki/doku.php



*自動車郚品の䟋の切り捚おられた゜ヌスコヌドのアヌカむブhttp://www.mstarproject.com/temp/3/sphinx/sphinxsearch_soruce.zip



*トリミングされたデヌタベヌスの䟋の構造のアヌカむブhttp://www.mstarproject.com/temp/3/sphinx/sphinxsearch_db_structure.zip



*デヌタhttp://www.mstarproject.com/temp/3/sphinx/sphinxsearch_db_data.zipを含む切り捚おられたサンプルデヌタベヌスのアヌカむブ43 MB



*スポンサヌリンクによるスポンサヌ tecdoc + sphinxsearchオンラむンストア開発



私は建蚭的な批刀に喜んで、質問に答えようずしたす。 ほずんどの堎合、サンクトペテルブルクでの䌚議には参加したせん。非垞に䞍快なフラむトであり、冬でもありたす。 私はこの蚘事からより倚くの利益があるず刀断し、りクラむナのスフィンクスの著者ず䌚うこずができたす。ただ埅぀必芁がありたす。



All Articles