Как убедиться, что все элементы в коллекции соответствуют фильтру в Azure Cognitive Search - PullRequest
1 голос
/ 21 января 2020

У меня Azure Cognitive Search работает, и мой индекс работает, как ожидалось. Мы пытаемся добавить фильтр безопасности в поиск, основываясь на разрешениях текущих пользователей. Полномочия пользователей приходят ко мне как IEnumerable, но в настоящее время я выбираю просто строку [] и передаю ее в свой фильтр, а затем делаю string.join, который выглядит следующим образом.

permission1, permission2, permission3, permission4

In наша база данных SQL, у нас есть представление, откуда индекс получает данные. В представлении есть столбец с именем RequiredPermissions, в индексе это Collection (Edm.string), и данные выглядят следующим образом.

[ 'permission1', 'permission2', 'permission3' ]

Требуется, чтобы запись возвращалась в В результате разрешения пользователя должны содержать все RequiredPermissions для этой записи.

Поэтому, если у нас есть пользователь со следующими разрешениями

permission1, permission3, permission5

И у нас есть следующие записи

Id, SearchText, Type,     Permissions
1,  abc,        User,     [ 'permission1', 'permission2' ]
2,  abc.pdf,    Document, [ 'permission1' ]
3,  abc,        Thing,    [ 'permission1', 'permission3' ]
4,  abc,        Stuff,    [ 'permission3', 'permission4' ]

Если пользователь выполнил поиск 'ab c', и эти четыре результата вернулись бы, мне нужно отфильтровать результаты, которые не имеют надлежащих разрешений. Поэтому я ожидал бы следующих результатов

Id, Returned, Reason
1,  no,       the user does not have permission2
2,  yes,      the user has permission1 and nothing else is needed
3,  yes,      the user has both permission1 and permission3
4,  no,       the user does not have permission4

Если я запустил следующий фильтр, я получу обратно все, что имеет разрешение 1 или разрешение 3, что недопустимо, поскольку пользователь не должен видеть элементы с идентификатором 1 или 4.

RequiredPermissions/any(role: search.in(role, 'permission1, permission3', ','))

Если я запускаю этот фильтр, то я ничего не получаю, все отклоняется, потому что ни у одной записи нет разрешения5, а у пользователя оно есть

RequiredPermissions/all(role: not search.in(role, 'permission1, permission3', ','))

Если я пытаюсь запустить поиск с использованием «все» и без «не» я получаю следующую ошибку

RequiredPermissions/all(role: search.in(role, 'permission1, permission3', ','))

Invalid expression: Invalid lambda expression. Found a test for equality or inequality where the opposite was expected in a lambda expression that iterates over a field of type Collection(Edm.String). For 'any', please use expressions of the form 'x eq y' or 'search.in(...)'. For 'all', please use expressions of the form 'x ne y', 'not (x eq y)', or 'not search.in(...)'.\r\nParameter name: $filter

Так что, похоже, я не могу использовать «не» с «любым», и я должен использовать «не» с 'all'

Для чего я хочу sh - это способ сказать, что у пользователя есть все разрешения в его списке, который находится в столбце RequiredPermissions.

В настоящее время я просто работаю в Почтальоне, используя RestApi, чтобы решить эту проблему, но я в конечном итоге перенесу это в. Net.

1 Ответ

3 голосов
/ 21 января 2020

Ваш сценарий не может быть реализован с помощью Collection(Edm.String) из-за ограничений на то, как all и any работают с такими коллекциями (задокументировано здесь ).

К счастью, есть альтернатива. Вы можете смоделировать разрешения как набор сложных типов, что позволяет вам использовать all так, как вам нужно для реализации вашей модели разрешений. Вот JSON пример того, как поле будет определено:

{
    "name": "test",
    "fields": [ 
        { "name": "Id", "type": "Edm.String", "key": true }, 
        { "name": "RequiredPermissions", "type": "Collection(Edm.ComplexType)", "fields": [{ "name": "Name", "type": "Edm.String" }] }
    ]
}

Вот JSON пример того, как документ будет выглядеть с определенными разрешениями:

{ "@search.action": "upload", "Id": "1", "RequiredPermissions": [{"Name": "permission1"}, {"Name": "permission2"}] }

Вот как можно создать фильтр, который дает желаемый эффект:

RequiredPermissions/all(perm: search.in(perm/Name, 'permission1,permission3,permission5'))

Пока это работает, вам настоятельно рекомендуется протестировать производительность этого решения с реалистичным набором данных c. Под капотом all выполняется как отрицательный any, а отрицательные запросы иногда могут плохо работать с типом инвертированных индексов, используемых поисковой системой.

Кроме того, имейте в виду, что в настоящее время существует ограничение на количество элементов во всех сложных коллекциях в документе. В настоящее время это ограничение составляет 3000. Таким образом, если RequiredPermissions была единственной сложной коллекцией в вашем индексе, это означает, что вы можете иметь максимум 3000 разрешений, определенных для документа.

...