2012-03-19 14 views
0

いくつかのドキュメントを探しているユーザーの読取り許可をスフィンクスインデックスで検索して確認します。アクセス権テーブルを使用しているスフィンクス検索エンジン

私はdoc_id、doc_titleとdoc_is_globalのドキュメントテーブルを持っています。 、

のuser_id、user_group_id、DOC_ID

ユーザーがdocument_categoriesに同等の識別子user_group_id、および文書と「USER_GROUP」にグループ化することができdoc_category_id:他の側では私のような構造を持つaccessprivilegesテーブルを持っています。アクセス表のようになり

USER_ID、user_group_id、DOC_IDは、1、NULL、NULL

NULL、12、NULL、32

1 doc_category_id 1、NULL、NULL、31

NULL、10,1、NULL

ユーザーは、is_globalフラグが1に設定されているか、user_idまたはuser_idによってアクセス権があるドキュメントのみを検索してください。無地のMySQLでは

私はいくつかのことで正しい結果を得ることが好きなジョイン:スフィンクスで

SELECT * from documents d 
    LEFT JOIN document_category dc ON dc.doc_id = d.doc_id 
    LEFT JOIN access a ON a.user_id = {$user} and a.doc_id = d.doc_id 
    LEFT JOIN access a ON a.category_id = dc.category_id and dc.group_id IN ({$groups}) 
    [...] 

、私が知っている、私は、インデックス付きのドキュメントに複数の属性を置くことができますが、それは私が欲しいものではありません。私の生産的なenvirenmentでは、私はどのユーザーが読み取りアクセス権を与えているかをチェックしなければならず、ユーザーがそれを行うことができる場合にのみ、ユーザーは読み取りアクセス権になります。これをチェックする可能性がない

access_user_id =(1,4,6,2)accessed_by_user =(1,5,3)

: はスフィンクスを使用して複数の属性を持つそのような状況を作られて、それは次のように返します。誰が誰に読書許可を与えたか。次の問題は、Sphinxがmaxをサポートしていることです。インデックスあたり4ギガバイトの属性。

は、私は、ユーザーが見ることが許可されていない結果フィルタリングするためのインデックスを構築するという考えのためにいくつかのヒントを必要とする(多分複数のインデックスと?)を

答えて

2

さてあなたはこのインデックスでき

sql_query = 
    SELECT d.doc_id, ... 
    GROUP_CONCAT(a.user_id) AS access_user_id, 
    GROUP_CONCAT(a.user_group_id) AS access_user_group_id 
    FROM documents d 
    LEFT JOIN document_category dc ON (dc.doc_id = d.doc_id) 
    LEFT JOIN access a ON (a.doc_id = d.doc_id OR a.doc_category_id = dc.category_id) 
    GROUP BY doc_id 

はその後

$cl->setSelect("*, IF(IN({$user},access_user_id),1,0)+IF(IN({$group},access_user_group_id),1,0) AS myint"); 
$cl->setFilter('myint',array(1,2)); 

次の問題は、スフィンクスが唯一の最大をサポートしていることであることに絞り込むことができます。インデックスあたり4ギガバイトの属性。

スフィンクスは4GBの文字列属性のインデックスのみをサポートしています。 MVA属性にこのような制限がありますか?

アトリビュートが多すぎると、インデックスは1つのインデックスになります。だから、部品へのインデックスをシャード:)


GROUP CONCATで最大の長さの問題に実行しているとして、最も簡単にはMVAクエリを使用することでprobabylでしょう。直接MVAのためのデータを取得するクエリが定義することができ、それはhttp://sphinxsearch.com/docs/current.html#conf-sql-attr-multi

にするために

は、ドキュメントを参照してください、

sql_query = SELECT d.doc_id, ... FROM documents d 
sql_attr_multi = uint access_user_id from query; SELECT DISTINCT doc_id, a.user_id FROM documents d 
    LEFT JOIN document_category dc ON (dc.doc_id = d.doc_id) 
    LEFT JOIN access a ON (a.doc_id = d.doc_id OR a.doc_category_id = dc.category_id) 
sql_attr_multi = uint access_user_group_id from query; SELECT DISTINCT doc_id, a.user_group_id FROM documents d 
    LEFT JOIN document_category dc ON (dc.doc_id = d.doc_id) 
    LEFT JOIN access a ON (a.doc_id = d.doc_id OR a.doc_category_id = dc.category_id) 

(おそらく、これらのクエリを最適化することができますGROUP_CONCAT/GROUP_BYの使用を回避少なくとも、開始するには十分な方法を示す必要があります)

+0

私はあなたに正しいヒントをくれました。今私はgroup_concat_max_lengthで問題に遭遇します。場合によっては、何千ものユーザーと共有しているドキュメントがある場合もあります。私はそれがすべてのデータが格納されている別のテーブルで動作すると思います。 Oracle DBMSでは、動的問合せを使用してpl/sqlプロシージャを作成し、access_user表など(パッケージdbms_sql)を反復処理してチャンク化されたデータを取得し、一時表に挿入します。私もPHPでそれを行うことができますが、私はそれが最良の考えではないと思います。 mysqlの問題を解決するためのヒントが2つありますか? – take

+0

回答を編集して、GROUP_CONCATを使用するための代替案を追加しました。 – barryhunter

+0

>>パーツのインデックスを分割する
どうすればいいですか? –

関連する問題