Бөлісу құралы:


Устранение неполадок с фильтрами коллекций OData в поиске ИИ Azure

Чтобы отфильтровать поля коллекции в службе "Поиск ИИ Azure", можно использоватьanyоператоры и all операторы вместе с лямбда-выражениями. Лямбда-выражение — это подфильтр, применяемый к каждому элементу коллекции.

Не все функции выражений-фильтров доступны в теле лямбда-выражения. Доступные функции зависят от типа данных поля коллекции, которое необходимо отфильтровать. Это может привести к ошибке при попытке использовать в лямбда-выражении функцию, которая не поддерживается в данном контексте. Если при попытке составить сложный фильтр по полям коллекции у вас возникают такие ошибки, эта статья поможет устранить их.

Распространенные ошибки фильтров коллекции

В таблице ниже перечислены ошибки, которые могут возникнуть при попытке выполнить фильтр коллекции. Эти ошибки возникают при использовании функций выражений фильтрации, которые не поддерживаются внутри лямбда-выражения. Для каждой ошибки приведены определенные рекомендации, помогающие переписать фильтр так, чтобы избежать ошибки. В таблице также есть ссылка на соответствующий раздел этой статьи с дополнительными сведениями о том, как избежать этой ошибки.

Сообщение об ошибке Ситуация Сведения
Функция ismatch не имеет параметров, привязанных к переменной диапазона 's'. Внутри лямбда-выражений (any и all) поддерживаются только ссылки на связанные поля. Однако вы можете изменить фильтр таким образом, чтобы ismatch функция находится за пределами лямбда-выражения и повторите попытку. Использование search.ismatch или search.ismatchscoring в лямбда-выражении Правила фильтрации сложных коллекций
Недопустимое лямбда-выражение. Обнаружена проверка на равенство или неравенство в ситуации, где ожидается обратное, в лямбда-выражении, которое выполняет итерацию по полю типа Collection(Edm.String). Для "any" используйте выражения формы "x eq y" или "search.in(...)". Для "all" используйте выражения формы "x ne y", "not (xq y)" или "не search.in(...)". Фильтрация по полю типа Collection(Edm.String) Правила фильтрации коллекций строк
Недопустимое лямбда-выражение. Обнаружена неподдерживаемая форма сложного логического выражения. Для "any" используйте выражения, которые являются "OR anDs", также известные как преобразовывающая обычная форма. Например, (a and b) or (c and d) где a, b, c и d являются сравнением или подтекстами равенства. Для "all" используйте выражения, которые являются anD of ORs, также известные как conjunctive Normal Form. Например, (a or b) and (c or d) где a, b, c и d являются сравнением или подтекстами неравенства. Примеры выражений сравнения: "x gt 5", "x le 2". Пример выражения равенства: "x eq 5". Пример выражения неравенства: "x ne 5". Фильтрация по полям типа Collection(Edm.DateTimeOffset), Collection(Edm.Double), Collection(Edm.Int32) или Collection(Edm.Int64) Правила фильтрации сравнимых коллекций
Недопустимое лямбда-выражение. Обнаружено неподдерживаемое использование geo.distance() или geo.intersects() в лямбда-выражении, которое выполняет итерацию по полю типа Collection(Edm.GeographyPoint). Для параметра any убедитесь, что вы сравниваете geo.distance() с помощью операторов lt или le и убедитесь, что любое использование geo.intersects() не отрицается. Для all сравнивайте geo.distance() с помощью операторов "gt" или "ge" и убедитесь, что ко всем экземплярам geo.intersects() применяется отрицания. Фильтрация по полю типа Collection(Edm.GeographyPoint) Правила фильтрации коллекций GeographyPoint
Недопустимое лямбда-выражение. Сложные логические выражения не поддерживаются в лямбда-выражениях, которые итерируются по полям типа Collection(Edm.GeographyPoint). Для "any" присоединяйте вложенные выражения с "or"; "и" не поддерживается. Для "all" присоединяйте вложенные выражения с "and"; "или" не поддерживается. Фильтрация по полям типа Collection(Edm.String) или Collection(Edm.GeographyPoint) Правила фильтрации коллекций строк

Правила фильтрации коллекций GeographyPoint
Недопустимое лямбда-выражение. Обнаружен оператор сравнения ("lt", "le", "gt" или "ge"). В лямбда-выражениях, которые выполняют итерацию по полям типа Collection(Edm.String), допускаются только операторы равенства. Для "any", se expressions формы "x eq y". Для "all" используйте выражения формы "x ne y" или "not (x eq y)". Фильтрация по полю типа Collection(Edm.String) Правила фильтрации коллекций строк

Составление допустимых фильтров коллекции

Правила составления допустимых фильтров коллекции зависят от типа данных. В следующих разделах описаны правила, в которых показаны примеры поддерживаемых и неподдерживаемых функций фильтрации.

Правила фильтрации коллекций строк

В лямбда-выражениях для коллекций строк можно использовать только операторы сравнения eq и ne.

Примечание.

Поиск ИИ Azure не поддерживает ltgtge/le//операторы строк, будь то внутри или за пределами лямбда-выражения.

Тело выражения any может проверять только на равенство, в то время как тело выражения all — только на неравенство.

Можно также объединить несколько выражений or в теле выражения any и через and — в теле выражения all. Поскольку функция search.in эквивалентна объединению проверок на равенство с or, она также разрешена в теле выражения any. И наоборот, not search.in допускается в теле выражения all.

Например, допустимы следующие выражения:

  • tags/any(t: t eq 'books')
  • tags/any(t: search.in(t, 'books, games, toys'))
  • tags/all(t: t ne 'books')
  • tags/all(t: not (t eq 'books'))
  • tags/all(t: not search.in(t, 'books, games, toys'))
  • tags/any(t: t eq 'books' or t eq 'games')
  • tags/all(t: t ne 'books' and not (t eq 'games'))

Хотя эти выражения не разрешены:

  • tags/any(t: t ne 'books')
  • tags/any(t: not search.in(t, 'books, games, toys'))
  • tags/all(t: t eq 'books')
  • tags/all(t: search.in(t, 'books, games, toys'))
  • tags/any(t: t eq 'books' and t ne 'games')
  • tags/all(t: t ne 'books' or not (t eq 'games'))

Правила фильтрации логических коллекций

Тип Edm.Boolean поддерживает только операторы eq и ne. Таким образом, не имеет смысла разрешать сочетание предложений, которые проверяют ту же переменную диапазона, с помощью and/or, так как это всегда ведет к тавтологии или противоречию.

Вот несколько примеров допустимых фильтров для логических коллекций:

  • flags/any(f: f)
  • flags/all(f: f)
  • flags/any(f: f eq true)
  • flags/any(f: f ne true)
  • flags/all(f: not f)
  • flags/all(f: not (f eq true))

В отличие от коллекций строк, для логических коллекций нет ограничений на возможность использования того или иного оператора в лямбда-выражении. Как eq, так и ne можно использовать в теле выражения any и all.

Выражения наподобие приведенного ниже для логических коллекций не допускаются:

  • flags/any(f: f or not f)
  • flags/any(f: f or f)
  • flags/all(f: f and not f)
  • flags/all(f: f and f eq true)

Правила фильтрации коллекций GeographyPoint

Значения типа Edm.GeographyPoint в коллекции нельзя сравнивать друг с другом напрямую. Вместо этого они должны использоваться в качестве параметров для функций geo.distance и geo.intersects. Функцию geo.distance, в свою очередь, необходимо сравнивать со значением расстояния с помощью одного из операторов сравнения lt, le, gt или ge. Эти правила также применяются к полям Edm.GeographyPoint.

Как и для коллекций строк, для коллекций Edm.GeographyPoint есть ряд правил относительно использования геопространственных функций и их объединения в различных типах лямбда-выражений.

  • То, какие операторы сравнения можно использовать с функцией geo.distance, зависит от типа лямбда-выражения. Для any можно использовать только lt и le. Для all можно использовать только gt и ge. Вы можете отменить выражения, связанные geo.distanceс этим, но необходимо изменить оператор сравнения (geo.distance(...) lt x становится not (geo.distance(...) ge x) и geo.distance(...) le x становится not (geo.distance(...) gt x)).
  • В теле выражения all функция geo.intersects должна быть инвертирована. И наоборот, в теле выражения any функция geo.intersects не должна быть инвертирована.
  • В теле выражения any геопространственные выражения можно объединять с помощью or. В теле выражения all такие выражения можно объединять с помощью and.

Приведенные выше ограничения установлены по тем же причинам, что и ограничения на равенство и неравенство в коллекциях строк. Дополнительные сведения об этих причинах см. в статье "Общие сведения о фильтрах коллекций OData" в поиске ИИ Azure.

Вот несколько примеров допустимых фильтров для коллекций Edm.GeographyPoint:

  • locations/any(l: geo.distance(l, geography'POINT(-122 49)') lt 10)
  • locations/any(l: not (geo.distance(l, geography'POINT(-122 49)') ge 10) or geo.intersects(l, geography'POLYGON((-122.031577 47.578581, -122.031577 47.678581, -122.131577 47.678581, -122.031577 47.578581))'))
  • locations/all(l: geo.distance(l, geography'POINT(-122 49)') ge 10 and not geo.intersects(l, geography'POLYGON((-122.031577 47.578581, -122.031577 47.678581, -122.131577 47.678581, -122.031577 47.578581))'))

Выражения, такие как следующие, не допускаются для Edm.GeographyPoint коллекций:

  • locations/any(l: l eq geography'POINT(-122 49)')
  • locations/any(l: not geo.intersects(l, geography'POLYGON((-122.031577 47.578581, -122.031577 47.678581, -122.131577 47.678581, -122.031577 47.578581))'))
  • locations/all(l: geo.intersects(l, geography'POLYGON((-122.031577 47.578581, -122.031577 47.678581, -122.131577 47.678581, -122.031577 47.578581))'))
  • locations/any(l: geo.distance(l, geography'POINT(-122 49)') gt 10)
  • locations/all(l: geo.distance(l, geography'POINT(-122 49)') lt 10)
  • locations/any(l: geo.distance(l, geography'POINT(-122 49)') lt 10 and geo.intersects(l, geography'POLYGON((-122.031577 47.578581, -122.031577 47.678581, -122.131577 47.678581, -122.031577 47.578581))'))
  • locations/all(l: geo.distance(l, geography'POINT(-122 49)') le 10 or not geo.intersects(l, geography'POLYGON((-122.031577 47.578581, -122.031577 47.678581, -122.131577 47.678581, -122.031577 47.578581))'))

Правила фильтрации сравнимых коллекций

Этот раздел относится ко всем следующим типам данных:

  • Collection(Edm.DateTimeOffset)
  • Collection(Edm.Double)
  • Collection(Edm.Int32)
  • Collection(Edm.Int64)

Такие типы, как Edm.Int32 и Edm.DateTimeOffset? поддерживают все шесть операторов сравнения: eq, ne, lt, le, gt и ge. Лямбда-выражения над коллекциями этих типов могут содержать простые выражения, использующие любой из этих операторов. Это относится к обоим any и all. Например, допустимы следующие фильтры:

  • ratings/any(r: r ne 5)
  • dates/any(d: d gt 2017-08-24T00:00:00Z)
  • not margins/all(m: m eq 3.5)

Однако существуют ограничения на то, как такие выражения сравнения можно объединять в более сложные конструкции в лямбда-выражении:

  • Правила для any:
    • Простые выражения неравенства не могут осмысленно объединяться с другими выражениями. Например, это выражение допустимо:

      • ratings/any(r: r ne 5)

      А это — нет:

      • ratings/any(r: r ne 5 and r gt 2)

      И хотя это выражение допустимо, оно не имеет смысла, поскольку условия перекрываются:

      • ratings/any(r: r ne 5 or r gt 7)
    • Простые выражения сравнения, включающие eq, lt, le, gt или ge, можно объединять с and/or. Например:

      • ratings/any(r: r gt 2 and r le 5)
      • ratings/any(r: r le 5 or r gt 7)
    • Выражения сравнения, объединенные с and (конъюнкции), можно объединять далее с помощью or. Эта форма известна в булевской логике как нормальная дизъюнктивная форма. Например:

      • ratings/any(r: (r gt 2 and r le 5) or (r gt 7 and r lt 10))
  • Правила для all:
    • Простые выражения равенства не могут осмысленно объединяться с другими выражениями. Например, это выражение допустимо:

      • ratings/all(r: r eq 5)

      А это — нет:

      • ratings/all(r: r eq 5 or r le 2)

      И хотя это выражение допустимо, оно не имеет смысла, поскольку условия перекрываются:

      • ratings/all(r: r eq 5 and r le 7)
    • Простые выражения сравнения, включающие ne, lt, le, gt или ge, можно объединять с and/or. Например:

      • ratings/all(r: r gt 2 and r le 5)
      • ratings/all(r: r le 5 or r gt 7)
    • Выражения сравнения, объединенные с or (дизъюнкции), можно объединять далее с помощью and. Эта форма известна в булевской логике как нормальная конъюнктивная форма. Например:

      • ratings/all(r: (r le 2 or gt 5) and (r lt 7 or r ge 10))

Правила фильтрации сложных коллекций

Лямбда-выражения над сложными коллекциями поддерживают гораздо более гибкий синтаксис, чем лямбда-выражения над коллекциями примитивных типов. В таком лямбда-выражении можно использовать любую конструкцию фильтра, которую можно использовать за его пределами, за исключением двух случаев.

Во-первых, внутри лямбда-выражений не поддерживаются функции search.ismatch и search.ismatchscoring. Дополнительные сведения см. в статье "Общие сведения о фильтрах коллекций OData" в службе "Поиск ИИ Azure".

Во-вторых, не допускаются ссылки на поля, которые не привязаны к переменной диапазона (так называемые свободные переменные). Например, рассмотрим следующие два эквивалентных выражения фильтра OData:

  1. stores/any(s: s/amenities/any(a: a eq 'parking')) and details/margin gt 0.5
  2. stores/any(s: s/amenities/any(a: a eq 'parking' and details/margin gt 0.5))

Первое выражение допускается, а вторая форма отклоняется, так как details/margin не привязана к переменной sдиапазона.

Это правило также распространяется на выражения, переменные в которых привязаны во внешней области. Такие переменные свободны по отношению к области, в которой они используются. Например, первое выражение является допустимым, а второе эквивалентное выражение — нет, так как поле s/name является свободным по отношению к области переменной диапазона a:

  1. stores/any(s: s/amenities/any(a: a eq 'parking') and s/name ne 'Flagship')
  2. stores/any(s: s/amenities/any(a: a eq 'parking' and s/name ne 'Flagship'))

Это ограничение не является проблемой на практике, поскольку всегда можно создать такие фильтры, в которых лямбда-выражения содержат только привязанные переменные.

Памятка по правилам для фильтров коллекций

В таблице ниже перечислены правила построения допустимых фильтров для каждого типа данных коллекции.

Тип данных Функции, допустимые в лямбда-выражениях с параметром any Функции, допустимые в лямбда-выражениях с параметром all
Collection(Edm.ComplexType) Все, кроме search.ismatch и search.ismatchscoring Одинаковые
Collection(Edm.String) Сравнения с помощью оператора eq или search.in

Объединение подвыражений с помощью оператора or
Сравнения с помощью оператора ne или not search.in()

Объединение подвыражений с помощью оператора and
Collection(Edm.Boolean) Сравнения с помощью оператора eq или ne Одинаковые
Collection(Edm.GeographyPoint) Использование geo.distance с оператором lt или le

geo.intersects

Объединение подвыражений с помощью оператора or
Использование geo.distance с оператором gt или ge

not geo.intersects(...)

Объединение подвыражений с помощью оператора and
Collection(Edm.DateTimeOffset), , Collection(Edm.Double)Collection(Edm.Int32)Collection(Edm.Int64) Сравнения с помощью оператора eq, ne, lt, gt, le или ge

Объединение сравнений с другими подвыражениями с помощью оператора or

Объединение сравнений, кроме выполненных с помощью оператора ne, с другими подвыражениями с помощью оператора and

Выражения, в которых используются сочетания операторов and и or в дизъюнктивной нормальной форме (ДНФ)
Сравнения с помощью оператора eq, ne, lt, gt, le или ge

Объединение сравнений с другими подвыражениями с помощью оператора and

Объединение сравнений, кроме выполненных с помощью оператора eq, с другими подвыражениями с помощью оператора or

Выражения, в которых используются сочетания операторов and и or в конъюнктивной нормальной форме (КНФ)

Примеры создания допустимых фильтров для каждого случая см. в разделе Составление допустимых фильтров коллекции.

Если вы часто пишете фильтры и понимаете правила из первых принципов, это поможет вам больше, чем просто запомнить их, см . статью "Общие сведения о фильтрах коллекций OData" в службе "Поиск ИИ Azure".

Следующие шаги