#azure-cognitive-search
#azure-когнитивный поиск
Вопрос:
Следующая инструкция найдите все профили, у которых есть Facebook или Twitter, и это сработает:
$filter=SocialAccounts/any(x: search.in(x, 'Facebook,Twitter'))
Но я не могу найти никаких примеров для поиска всего, что имеет Facebook и Twitter. Я пытался:
$filter=SocialAccounts/all(x: search.in(x, 'Facebook,Twitter'))
Но это недопустимый запрос.
Ответ №1:
Azure Search не поддерживает тип фильтра ‘все’, который вы ищете. Использование search.in использование ‘all’ было бы эквивалентно использованию OR, но Azure Search может обрабатывать только AND в теле лямбда-выражения ‘all’ (что эквивалентно OR в теле ‘any’ лямбда-выражения).
Вы могли бы попробовать обходной путь, подобный этому:
$filter=tags/any(t: t eq 'Facebook') and tags/any(t: t eq 'Twitter')
Однако на самом деле это не эквивалентно использованию all
с search.in
. Запрос, выраженный с помощью all
, соответствует документам, в которых каждая социальная учетная запись является строго Facebook или Twitter. Если присутствует любая другая учетная запись социальной сети, документ не будет соответствовать. Обходной путь не обладает этим свойством. Для соответствия документу должны быть, по крайней мере, Facebook и Twitter, но не только они. Это, безусловно, допустимый сценарий; это просто не то же самое, что использовать all
with search.in
, что было первоначальным вопросом.
Независимо от того, как вы пытаетесь переписать запрос, вы не сможете выразить эквивалент all
запроса. Это ограничение связано с тем, как Azure Search хранит коллекции строк и других примитивных типов в инвертированном индексе.
Пожалуйста, проголосуйте за голос пользователя, чтобы помочь расставить приоритеты: https://feedback.azure.com/forums/263029-azure-search/suggestions/37166749-efficient-way-to-express-a-true-all
Возможным обходным путем является использование новой функции сложных типов, которая позволяет использовать более выразительные фильтры внутри лямбда-выражений. Например, если вы моделируете теги как объекты с одним value
свойством, а не как набор строк, вы должны быть в состоянии выполнить фильтр, подобный этому:
$filter=tags/all(t: search.in(t/value, 'Facebook,Twitter'))
В REST API вы бы определили tags
следующим образом:
{
"name": "myindex",
"fields": [
...
{
"name": "tags",
"type": "Collection(Edm.ComplexType)",
"fields": [
{ "name": "value", "type": "Edm.String", "filterable": true }
]
}
]
}
Обратите внимание, что на момент написания этой статьи эта функция находится в предварительном просмотре, но скоро станет общедоступной (и публично задокументирована).
Комментарии:
1. Предложенный вами обходной путь на самом деле неверен. В этом сценарии нет способа достичь эквивалента ‘all’. Подробности смотрите в моем ответе на User Voice. Я опубликую ответ, основанный на этом.
2. Я буду обращаться к тебе внутренне, Брюс.
3. Томас, не могли бы вы, пожалуйста, пометить этот ответ как принятый? Таким образом, я закрываю дубликаты и указываю их здесь.
4. Готово, спасибо, Брюс.