Sphinx Search Engine использует таблицу прав доступа - PullRequest
0 голосов
/ 19 марта 2012

Я хочу проверить при поиске по индексу sphinx разрешение на чтение для пользователя, который ищет некоторые документы.

Например, у меня есть таблица документов с doc_id, doc_title и doc_is_global.С другой стороны, у меня есть таблица accessprivileges со структурой, такой как:

user_id, user_group_id, doc_id, doc_category_id

пользователи могут группироваться в «user_group» с идентификатором user_group_id, и документы эквивалентны в document_categories.

Таблица доступа может выглядеть следующим образом:

user_id, user_group_id, doc_id, doc_category_id

1, NULL, 1, NULL

NULL,12, NULL, 32

1, NULL, NULL, 31

NULL, 10, 1, NULL

Пользователь должен находить документы только с флагом is_globalустановлен в 1, или он имеет доступ по своему user_id, или по group_id, членом которого он является.

В простом MySQL я получаю правильный результат с помощью некоторых JOINs, таких как:

    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})
    [...]

В SphinxЯ знаю, я могу поместить несколько атрибутов в индексированный документ, но это не то, что я хочу.В моей продуктивной среде я также должен проверить, какой пользователь предоставил доступ для чтения, и только если он может это сделать, он становится доступным для чтения.В такой ситуации с несколькими атрибутами с использованием sphinx он возвращает что-то вроде:

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

, поэтому нетвозможность проверить, кто дал разрешение на чтение, кому.Следующая проблема заключается в том, что Sphinx поддерживает только макс.Атрибуты 4gb на индекс.

Мне нужна подсказка для идеи построения индекса, чтобы отфильтровать результаты, которые пользователь не может видеть (возможно, с несколькими индексами?)

1 Ответ

2 голосов
/ 19 марта 2012

Ну, вы можете индексировать это с помощью

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));

Следующая проблема заключается в том, что Sphinx поддерживает только макс.Атрибуты 4 ГБ на индекс.

Sphinx поддерживает только 4 ГБ строковых атрибутов на индекс.Вы уверены, что существует такой предел для атрибутов MVA?

В любом случае, если слишком много атрибутов - это ограничение на индекс.Поэтому разделите индекс на части:)


Поскольку при работе с GROUP CONCAT возникают проблемы с максимальной длиной, проще всего было бы использовать запрос MVA.

См. Документацию по нему http://sphinxsearch.com/docs/current.html#conf-sql-attr-multi

Здесь можно определить запрос для извлечения данных для MVA напрямую, избегая использования GROUP_CONCAT / GROUP_BY

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)

(возможно, может немного оптимизировать эти запросы, но, по крайней мере, должен показать, насколько достаточно для начала)

...