OData-$filter syntax i Azure AI Search

I Azure AI Search anger parametern $filter inkluderings- eller exkluderingsvillkor för att returnera matchningar i sökresultat. Den här artikeln beskriver OData-syntaxen för $filter och innehåller exempel.

Konstruktion och konstanter för fältvägar beskrivs i översikten över OData-språket i Azure AI Search. Mer information om filterscenarier finns i Filter i Azure AI Search.

Syntax

Ett filter i OData-språket är ett booleskt uttryck, som i sin tur kan vara en av flera typer av uttryck, vilket visas i följande EBNF (Extended Backus-Naur Form):

boolean_expression ::=
    collection_filter_expression
    | logical_expression
    | comparison_expression
    | boolean_literal
    | boolean_function_call
    | '(' boolean_expression ')'
    | variable

/* This can be a range variable in the case of a lambda, or a field path. */
variable ::= identifier | field_path

Ett interaktivt syntaxdiagram är också tillgängligt:

Typerna av booleska uttryck är:

  • Samlingsfilteruttryck med eller anyall. Dessa tillämpar filtervillkor på samlingsfält. Mer information finns i OData-insamlingsoperatorer i Azure AI Search.
  • Logiska uttryck som kombinerar andra booleska uttryck med operatorerna and, oroch not. Mer information finns i Logiska OData-operatorer i Azure AI Search.
  • Jämförelseuttryck som jämför fält eller intervallvariabler med konstanta värden med operatorerna eq, , negt, lt, geoch le. Mer information finns i OData-jämförelseoperatorer i Azure AI Search. Jämförelseuttryck används också för att jämföra avstånd mellan geo-spatiala koordinater med hjälp av geo.distance funktionen. Mer information finns i OData geo-spatiala funktioner i Azure AI Search.
  • De booleska literalerna true och false. Dessa konstanter kan vara användbara ibland när programmatiskt genererar filter, men annars tenderar de inte att användas i praktiken.
  • Anrop till booleska funktioner, inklusive:
  • Fältsökvägar eller intervallvariabler av typen Edm.Boolean. Om ditt index till exempel har ett booleskt fält som heter IsEnabled och du vill returnera alla dokument där det här fältet är truekan filteruttrycket bara vara namnet IsEnabled.
  • Booleska uttryck inom parenteser. Att använda parenteser kan hjälpa till att uttryckligen fastställa ordningen på åtgärder i ett filter. Mer information om standardprioriteten för OData-operatorerna finns i nästa avsnitt.

Operatorprioret i filter

Om du skriver ett filteruttryck utan parenteser runt dess underuttryck utvärderar Azure AI Search det enligt en uppsättning regler för operatorprioritet. Dessa regler baseras på vilka operatorer som används för att kombinera underuttryck. I följande tabell visas grupper med operatorer i ordning från högsta till lägsta prioritet:

Grupp Operatorer
Logiska operatorer not
Jämförelseoperatorer eq, ne, gt, lt, , , gele
Logiska operatorer and
Logiska operatorer or

En operator som är högre i tabellen ovan "binder hårdare" till sina operander än andra operatorer. Till exempel and har högre prioritet än or, och jämförelseoperatorer har högre prioritet än någon av dem, så följande två uttryck är likvärdiga:

    Rating gt 0 and Rating lt 3 or Rating gt 7 and Rating lt 10
    ((Rating gt 0) and (Rating lt 3)) or ((Rating gt 7) and (Rating lt 10))

Operatorn not har den högsta prioriteten av alla – till och med högre än jämförelseoperatorerna. Det är därför du försöker skriva ett filter som det här:

    not Rating gt 5

Du får det här felmeddelandet:

    Invalid expression: A unary operator with an incompatible type was detected. Found operand type 'Edm.Int32' for operator kind 'Not'.

Det här felet inträffar eftersom operatorn är associerad med bara Rating fältet, som är av typen Edm.Int32, och inte med hela jämförelseuttrycket. Korrigeringen är att placera operand i not parenteser:

    not (Rating gt 5)

Begränsningar för filterstorlek

Det finns gränser för storlek och komplexitet för filteruttryck som du kan skicka till Azure AI Search. Gränserna baseras ungefär på antalet satser i filteruttrycket. En bra riktlinje är att om du har hundratals satser riskerar du att överskrida gränsen. Vi rekommenderar att du utformar programmet på ett sådant sätt att det inte genererar filter av obundna storlekar.

Dricks

Genom att search.in använda funktionen i stället för långa disjunctions av likhetsjämförelser kan du undvika filtersatsens gräns, eftersom ett funktionsanrop räknas som en enda sats.

Exempel

Hitta alla hotell med minst ett rum med ett baspris som är mindre än 200 USD och som är klassificerat till eller över 4:

    $filter=Rooms/any(room: room/BaseRate lt 200.0) and Rating ge 4

Hitta alla hotell förutom "Sea View Motel" som har renoverats sedan 2010:

    $filter=HotelName ne 'Sea View Motel' and LastRenovationDate ge 2010-01-01T00:00:00Z

Hitta alla hotell som renoverades 2010 eller senare. Datetime-literalen innehåller tidszonsinformation för Pacific Standard Time:

    $filter=LastRenovationDate ge 2010-01-01T00:00:00-08:00

Hitta alla hotell som har parkering ingår och där alla rum är rökfria:

    $filter=ParkingIncluded and Rooms/all(room: not room/SmokingAllowed)

- OR -

    $filter=ParkingIncluded eq true and Rooms/all(room: room/SmokingAllowed eq false)

Hitta alla hotell som är lyxiga eller inkluderar parkering och har betyget 5:

    $filter=(Category eq 'Luxury' or ParkingIncluded eq true) and Rating eq 5

Hitta alla hotell med taggen "wifi" i minst ett rum (där varje rum har taggar lagrade i ett Collection(Edm.String) fält):

    $filter=Rooms/any(room: room/Tags/any(tag: tag eq 'wifi'))

Hitta alla hotell med alla rum:

    $filter=Rooms/any()

Hitta alla hotell som inte har rum:

    $filter=not Rooms/any()

Hitta alla hotell inom 10 kilometer från en viss referenspunkt (där Location är ett fält av typen Edm.GeographyPoint):

    $filter=geo.distance(Location, geography'POINT(-122.131577 47.678581)') le 10

Hitta alla hotell i en viss vyport som beskrivs som en polygon (där Location är ett fält av typen Edm.GeographyPoint). Polygonen måste stängas, vilket innebär att de första och sista punktuppsättningarna måste vara desamma. Poängen måste också anges i motsols ordning.

    $filter=geo.intersects(Location, geography'POLYGON((-122.031577 47.578581, -122.031577 47.678581, -122.131577 47.678581, -122.031577 47.578581))')

Hitta alla hotell där fältet "Beskrivning" är null. Fältet är null om det aldrig har angetts eller om det uttryckligen har angetts till null:

    $filter=Description eq null

Hitta alla hotell med namn som är lika med antingen "Sea View motel" eller "Budget hotel"). De här fraserna innehåller blanksteg och blanksteg är en standardgränsare. Du kan ange en alternativ avgränsare inom enkla citattecken som den tredje strängparametern:

    $filter=search.in(HotelName, 'Sea View motel,Budget hotel', ',')

Hitta alla hotell med namnet "Sea View Motel" eller "Budget hotel" avgränsat med |):

    $filter=search.in(HotelName, 'Sea View motel|Budget hotel', '|')

Hitta alla hotell där alla rum har taggen "wifi" eller "tub":

    $filter=Rooms/any(room: room/Tags/any(tag: search.in(tag, 'wifi, tub')))

Hitta en matchning på fraser i en samling, till exempel "uppvärmda handduksställ" eller "hårtork som ingår" i taggar.

    $filter=Rooms/any(room: room/Tags/any(tag: search.in(tag, 'heated towel racks,hairdryer included', ','))

Hitta dokument med ordet "vattnet". Den här filterfrågan är identisk med en sökbegäran med search=waterfront.

    $filter=search.ismatchscoring('waterfront')

Hitta dokument med ordet "vandrarhem" och betyg större eller lika med 4, eller dokument med ordet "motell" och betyg lika med 5. Det gick inte att uttrycka den search.ismatchscoring här begäran utan funktionen eftersom den kombinerar fulltextsökning med filteråtgärder med hjälp av or.

    $filter=search.ismatchscoring('hostel') and rating ge 4 or search.ismatchscoring('motel') and rating eq 5

Hitta dokument utan ordet "lyx".

    $filter=not search.ismatch('luxury')

Hitta dokument med frasen "ocean view" eller klassificering som är lika med 5. Frågan search.ismatchscoring körs endast mot fält HotelName och Description. Dokument som endast matchade den andra satsen i disjunction returneras också - hotell med lika med Rating 5. Dessa dokument returneras med poäng som är lika med noll för att klargöra att de inte matchade någon av de poängsatta delarna i uttrycket.

    $filter=search.ismatchscoring('"ocean view"', 'Description,HotelName') or Rating eq 5

Hitta hotell där termerna "hotell" och "flygplats" inte är mer än fem ord ifrån varandra i beskrivningen och där alla rum är rökfria. Den här frågan använder det fullständiga Lucene-frågespråket.

    $filter=search.ismatch('"hotel airport"~5', 'Description', 'full', 'any') and not Rooms/any(room: room/SmokingAllowed)

Hitta dokument som har ett ord som börjar med bokstäverna "lux" i fältet Beskrivning. Den här frågan använder prefixsökning i kombination med search.ismatch.

    $filter=search.ismatch('lux*', 'Description')

Nästa steg