Azure AI 搜尋服務中的「簡單」搜尋查詢範例
在 Azure AI 搜尋服務中,簡單查詢語法會叫用預設查詢剖析器進行全文檢索搜尋。 剖析器速度快,可處理常見案例,包括全文檢索搜尋、篩選搜尋、多面向搜尋和前置詞搜尋。 本文使用範例來說明搜尋文件 (REST API) 要求中的簡單語法使用方式。
注意
替代的查詢語法是完整 Lucene,可支援如模糊和萬用字元搜尋等較複雜的查詢結構。 如需詳細資訊和範例,請參閱使用完整的 Lucene 語法。
飯店範例索引
下列查詢是以 hotels-sample-index 為基礎,您可以遵循本快速入門中的指示來建立。
範例查詢會使用 REST API 和 POST 要求來表達。 您可以在 REST 用戶端貼上並加以執行。 在 Azure 入口網站中使用搜尋總管的 JSON 檢視。 在 JSON 檢視中,您可以貼上本文此處所示的查詢範例。
要求標頭必須具有下列值:
機碼 | 值 |
---|---|
內容-類型 | application/json |
api-key | <your-search-service-api-key> (查詢或系統管理金鑰) |
URI 參數必須包含具有索引名稱、文件集合、搜尋命令和 API 版本的搜尋服務端點,類似於下列範例:
https://{{service-name}}.search.windows.net/indexes/hotels-sample-index/docs/search?api-version=2024-07-01
要求本文應格式化為有效的 JSON:
{
"search": "*",
"queryType": "simple",
"select": "HotelId, HotelName, Category, Tags, Description",
"count": true
}
設定為
*
的「search」是未指定的查詢,相當於 Null 或空白搜尋。 這並不特別有用,但這是您可以執行的最簡單搜尋,而且其會顯示索引中所有可擷取的欄位,以及所有值。「queryType」設定為「simple」是預設值,可以省略,但包含它是為了進一步強調本文中的查詢範例是用簡單語法表示的。
設定為以逗號分隔的欄位清單的「select」用於搜尋結果組合,只包含搜尋結果內容中有用的欄位。
「count」會傳回符合搜尋準則的文件數目。 在空的搜尋字串上,此計數將會是索引中的所有文件 (在 hotels-sample-index 中,計數為 50)。
範例 1:全文檢索搜尋
全文檢索搜尋可以是任意數目的獨立字詞或引號括起來的片語,包含或不包含布林運算子。
POST /indexes/hotel-samples-index/docs/search?api-version=2024-07-01
{
"search": "pool spa +airport",
"searchMode": "any",
"queryType": "simple",
"select": "HotelId, HotelName, Category, Description",
"count": true
}
由重要字詞或片語組成的關鍵字搜尋通常是最適合的。 字串欄位會在編製索引和查詢、卸除非必要字組 (例如「the」、「and」、「it」) 期間進行文字分析。 若要查看查詢字串如何在索引中標記化,請在 Analyze Text 呼叫中,將字串傳遞至索引。
「searchMode」參數可控制精確度和重新叫用。 如果您想要更多重新叫用,請使用預設的「any」值,這樣如果符合查詢字串的任何部分,就會傳回結果。 如果您偏好精確度,必須比對字串的所有部分,請將 searchMode 變更為「all」。 請嘗試上述兩種查詢方式,以查看 searchMode 如何變更結果。
「pool spa +airport」查詢的回應看起來應該類似下列範例,為了簡潔起見,我們進行刪減。
"@odata.count": 6,
"value": [
{
"@search.score": 7.3617697,
"HotelId": "21",
"HotelName": "Nova Hotel & Spa",
"Description": "1 Mile from the airport. Free WiFi, Outdoor Pool, Complimentary Airport Shuttle, 6 miles from the beach & 10 miles from downtown.",
"Category": "Resort and Spa",
"Tags": [
"pool",
"continental breakfast",
"free parking"
]
},
{
"@search.score": 2.5560288,
"HotelId": "25",
"HotelName": "Scottish Inn",
"Description": "Newly Redesigned Rooms & airport shuttle. Minutes from the airport, enjoy lakeside amenities, a resort-style pool & stylish new guestrooms with Internet TVs.",
"Category": "Luxury",
"Tags": [
"24-hour front desk service",
"continental breakfast",
"free wifi"
]
},
{
"@search.score": 2.2988036,
"HotelId": "35",
"HotelName": "Suites At Bellevue Square",
"Description": "Luxury at the mall. Located across the street from the Light Rail to downtown. Free shuttle to the mall and airport.",
"Category": "Resort and Spa",
"Tags": [
"continental breakfast",
"air conditioning",
"24-hour front desk service"
]
}
]
請注意回應中的搜尋分數。 這是相符項目的相關性分數。 根據預設,搜尋服務會根據此分數傳回前 50 個相符項目。
沒有排名時,分數一律為「1.0」,這是因為搜尋不是全文檢索搜尋,或是未提供任何準則。 例如,在空白搜尋 (search= *
) 中,資料列會依任意順序返回。 當您包含實際準則時,您會發現搜尋分數逐漸具有其實質意義。
範例 2︰依識別碼查閱
當在查詢中傳回搜尋結果時,合乎邏輯的下一步是提供一個詳細資料頁面,其中包含來自文件的更多欄位。 此範例示範如何使用查閱文件,透過傳入文件識別碼來傳回單一文件。
GET /indexes/hotels-sample-index/docs/41?api-version=2024-07-01
所有文件都有唯一識別碼。 如果您使用入口網站,請從 [索引] 索引標籤中選取索引,然後查看欄位定義以判斷哪個欄位是索引鍵。 使用 REST,Get Index 呼叫會傳回回應本文中的索引定義。
上述查詢的回應是由索引鍵為 41 的文件所組成。 在索引定義中標示為「可擷取」的任何欄位都可以在搜尋結果中傳回,並在您的應用程式中轉譯。
{
"HotelId": "41",
"HotelName": "Ocean Air Motel",
"Description": "Oceanfront hotel overlooking the beach features rooms with a private balcony and 2 indoor and outdoor pools. Various shops and art entertainment are on the boardwalk, just steps away.",
"Description_fr": "L'hôtel front de mer surplombant la plage dispose de chambres avec balcon privé et 2 piscines intérieures et extérieures. Divers commerces et animations artistiques sont sur la promenade, à quelques pas.",
"Category": "Budget",
"Tags": [
"pool",
"air conditioning",
"bar"
],
"ParkingIncluded": true,
"LastRenovationDate": "1951-05-10T00:00:00Z",
"Rating": 3.5,
"Location": {
"type": "Point",
"coordinates": [
-157.846817,
21.295841
],
"crs": {
"type": "name",
"properties": {
"name": "EPSG:4326"
}
}
},
"Address": {
"StreetAddress": "1450 Ala Moana Blvd 2238 Ala Moana Ctr",
"City": "Honolulu",
"StateProvince": "HI",
"PostalCode": "96814",
"Country": "USA"
}
}
範例 3:篩選文字
篩選語法是您可搭配 search
使用或單獨使用的 OData 運算式。 搭配使用時,會先將 filter
套用到整個索引,再對篩選結果執行搜尋。 由於篩選能夠減少搜尋查詢需要處理的資料集合,因此對於提升查詢效能方面是很實用的技術。
您可以在索引定義中標示為 filterable
的任何欄位上定義篩選條件。 對於 hotels-sample-index,可篩選的欄位包括 Category、Tags、ParkingIncluded、Rating 和大部分的 Address 欄位。
POST /indexes/hotels-sample-index/docs/search?api-version=2024-07-01
{
"search": "art tours",
"queryType": "simple",
"filter": "Category eq 'Resort and Spa'",
"searchFields": "HotelName,Description,Category",
"select": "HotelId,HotelName,Description,Category",
"count": true
}
上述查詢的回應範圍僅限於分類為「Report and Spa」的旅館,其中包含「art」或「tours」等詞彙。 在此情況下,只有一個相符項目。
{
"@search.score": 2.8576312,
"HotelId": "31",
"HotelName": "Santa Fe Stay",
"Description": "Nestled on six beautifully landscaped acres, located 2 blocks from the Plaza. Unwind at the spa and indulge in art tours on site.",
"Category": "Resort and Spa"
}
範例 4:篩選函式
篩選條件運算式可以包含 「search.ismatch」和「search.ismatchscoring」函式,讓您在篩選條件內建置搜尋查詢。 此篩選條件運算式會針對 free 使用萬用字元來選取便利設施,包含免費 wifi、免費停車等。
POST /indexes/hotels-sample-index/docs/search?api-version=2024-07-01
{
"search": "",
"filter": "search.ismatch('free*', 'Tags', 'full', 'any')",
"select": "HotelId, HotelName, Category, Description",
"count": true
}
上述查詢的回應會比對 19 家提供免費便利設施的旅館。 請注意,搜尋分數在整個結果中都是統一的「1.0」。 這是因為搜尋運算式為 Null 或空白,導致逐字篩選條件相符,但全文檢索搜尋則否。 相關性分數只會在全文檢索搜尋時傳回。 如果您使用沒有 search
的篩選條件,請確定您有足夠的可排序欄位,以便控制搜尋排名。
"@odata.count": 19,
"value": [
{
"@search.score": 1.0,
"HotelId": "31",
"HotelName": "Santa Fe Stay",
"Tags": [
"view",
"restaurant",
"free parking"
]
},
{
"@search.score": 1.0,
"HotelId": "27",
"HotelName": "Super Deluxe Inn & Suites",
"Tags": [
"bar",
"free wifi"
]
},
{
"@search.score": 1.0,
"HotelId": "39",
"HotelName": "Whitefish Lodge & Suites",
"Tags": [
"continental breakfast",
"free parking",
"free wifi"
]
},
{
"@search.score": 1.0,
"HotelId": "11",
"HotelName": "Regal Orb Resort & Spa",
"Tags": [
"free wifi",
"restaurant",
"24-hour front desk service"
]
},
範例 5︰範圍篩選條件
範圍篩選是透過適用於任何資料類型的篩選條件運算式來支援。 下列範例說明數值和字串範圍。 資料類型在範圍篩選條件中很重要,而當數值資料位於數值欄位且字串資料位於字串欄位時效果最好。 字串欄位中的數值資料不適合用於範圍,因為數值字串無法比較。
下列查詢是數值範圍。 在 hotels-sample-index 中,唯一可篩選的數值欄位是 Rating。
POST /indexes/hotels-sample-index/docs/search?api-version=2024-07-01
{
"search": "*",
"filter": "Rating ge 2 and Rating lt 4",
"select": "HotelId, HotelName, Rating",
"orderby": "Rating desc",
"count": true
}
查詢的回應看起來應該類似下列範例,為了簡潔起見,我們進行刪減。
"@odata.count": 27,
"value": [
{
"@search.score": 1.0,
"HotelId": "22",
"HotelName": "Stone Lion Inn",
"Rating": 3.9
},
{
"@search.score": 1.0,
"HotelId": "25",
"HotelName": "Scottish Inn",
"Rating": 3.8
},
{
"@search.score": 1.0,
"HotelId": "2",
"HotelName": "Twin Dome Motel",
"Rating": 3.6
}
...
下一個查詢是字串欄位 (Address/StateProvince) 的範圍篩選條件:
POST /indexes/hotels-sample-index/docs/search?api-version=2024-07-01
{
"search": "*",
"filter": "Address/StateProvince ge 'A*' and Address/StateProvince lt 'D*'",
"select": "HotelId, HotelName, Address/StateProvince",
"count": true
}
查詢的回應看起來應該類似下列範例,為了簡潔起見進行了刪減。 在此範例中,無法依 StateProvince 排序,因為欄位不會在索引定義中屬性化為「可排序」。
"@odata.count": 9,
"value": [
{
"@search.score": 1.0,
"HotelId": "9",
"HotelName": "Smile Hotel",
"Address": {
"StateProvince": "CA "
}
},
{
"@search.score": 1.0,
"HotelId": "39",
"HotelName": "Whitefish Lodge & Suites",
"Address": {
"StateProvince": "CO"
}
},
{
"@search.score": 1.0,
"HotelId": "7",
"HotelName": "Countryside Resort",
"Address": {
"StateProvince": "CA "
}
},
...
範例 6:地理空間搜尋
hotels-sample 索引包含具有經度和緯度座標的 Location 欄位。 這個範例會使用 geo.distance 函式,以篩選起始點周圍以至您提供的任意距離 (以公里為單位) 內的文件。 您可以調整查詢 (10) 中的最後一個值,以縮小或放大查詢的介面區。
POST /indexes/v/docs/search?api-version=2024-07-01
{
"search": "*",
"filter": "geo.distance(Location, geography'POINT(-122.335114 47.612839)') le 10",
"select": "HotelId, HotelName, Address/City, Address/StateProvince",
"count": true
}
此查詢的回應會傳回距離所提供座標 10 公里內的所有旅館:
{
"@odata.count": 3,
"value": [
{
"@search.score": 1.0,
"HotelId": "45",
"HotelName": "Arcadia Resort & Restaurant",
"Address": {
"City": "Seattle",
"StateProvince": "WA"
}
},
{
"@search.score": 1.0,
"HotelId": "24",
"HotelName": "Gacc Capital",
"Address": {
"City": "Seattle",
"StateProvince": "WA"
}
},
{
"@search.score": 1.0,
"HotelId": "16",
"HotelName": "Double Sanctuary Resort",
"Address": {
"City": "Seattle",
"StateProvince": "WA"
}
}
]
}
範例 7︰使用 searchMode 的布林值
簡單語法支援字元形式的布林運算子 (+, -, |
),以支援 AND、OR 和 NOT 查詢邏輯。 布林搜尋的行為會如預期般運作,但有一些值得注意的例外狀況。
在先前的範例中,searchMode
參數已引進為影響精確度和重新叫用的機制,其中 "searchMode": "any"
偏好重新叫用 (符合任何準則的文件會視為是相符項目),而「searchMode=all」則偏好精確度 (所有準則都必須在文件中比對)。
在布林搜尋的執行內容中,如果您以多個運算子堆疊查詢,並取得較廣泛的結果 (而非較狹隘的結果),預設 "searchMode": "any"
可能會造成混淆。 在使用 NOT 更是如此,因為其結果會包含所有「不包含」特定字詞的文件。
下列範例提供一個實例。 使用 searchMode (any) 執行下列查詢,會傳回 42 份文件:包含「restaurant」一詞的文件,加上沒有「air conditioning」片語的所有文件。
請注意,布林運算子 (-
) 與片語「air conditioning」之間沒有空格。
POST /indexes/hotels-sample-index/docs/search?api-version=2024-07-01
{
"search": "restaurant -\"air conditioning\"",
"searchMode": "any",
"searchFields": "Tags",
"select": "HotelId, HotelName, Tags",
"count": true
}
變更為 "searchMode": "all"
會對準則強制執行累積效果,並傳回較小的結果集 (7 個相符項目),該結果集由包含「restaurant」一詞的文件減去包含片語「air conditioning」的文件組成。
查詢的回應看起來應該類似下列範例,為了簡潔起見進行了刪減。
"@odata.count": 7,
"value": [
{
"@search.score": 2.5460577,
"HotelId": "11",
"HotelName": "Regal Orb Resort & Spa",
"Tags": [
"free wifi",
"restaurant",
"24-hour front desk service"
]
},
{
"@search.score": 2.166792,
"HotelId": "10",
"HotelName": "Countryside Hotel",
"Tags": [
"24-hour front desk service",
"coffee in lobby",
"restaurant"
]
},
...
範例 8:分頁結果
在先前的範例中,您已了解影響搜尋結果組合的參數,包括 select
,此參數可決定結果中的欄位、排序次序,以及如何包含所有相符項目的計數。 此範例是分頁參數形式之搜索結果組合的延續,可讓您批次處理出現在任何指定頁面中的結果數目。
根據預設,搜尋服務會傳回前 50 個相符項目。 若要控制每個頁面中的符合項目數,請使用 top
來定義批次的大小,然後使用 skip
來挑選後續的批次。
下列範例會在 Rating 欄位上使用篩選條件和排序次序 (Rating 欄位可同時進行篩選和排序),因為這樣能更容易看到對排序結果進行分頁的效果。 在一般完整搜尋查詢中,最符合的相符項目會依 @search.score
進行排名與分頁。
POST /indexes/hotels-sample-index/docs/search?api-version=2024-07-01
{
"search": "*",
"filter": "Rating gt 4",
"select": "HotelName, Rating",
"orderby": "Rating desc",
"top": "5",
"count": true
}
此查詢會尋找 21 份相符文件,但因為您指定了 top
,所以回應只會傳回前五個相符項目,且評等由 4.9 開始,並以 4.7 結束 (「Lady of the Lake B & B」)。
若要取得後續的 5 份文件,請略過第一個批次:
POST /indexes/hotels-sample-index/docs/search?api-version=2024-07-01
{
"search": "*",
"filter": "Rating gt 4",
"select": "HotelName, Rating",
"orderby": "Rating desc",
"top": "5",
"skip": "5",
"count": true
}
第二個批次的回應會略過前五個相符項目,從「Pull'r Inn Motel」開始傳回接下來的五個相符項目。 若要繼續執行其他批次,請將 top
維持在 5,然後在每個新的要求上將 skip
依 5 遞增 (skip=5、skip=10、skip=15,依此類推)。
"value": [
{
"@search.score": 1.0,
"HotelName": "Pull'r Inn Motel",
"Rating": 4.7
},
{
"@search.score": 1.0,
"HotelName": "Sublime Cliff Hotel",
"Rating": 4.6
},
{
"@search.score": 1.0,
"HotelName": "Antiquity Hotel",
"Rating": 4.5
},
{
"@search.score": 1.0,
"HotelName": "Nordick's Motel",
"Rating": 4.5
},
{
"@search.score": 1.0,
"HotelName": "Winter Panorama Resort",
"Rating": 4.5
}
]
下一步
現在您已使用基本查詢語法進行一些練習,請嘗試以程式碼指定查詢。 下列連結說明如何使用 Azure SDK 設定搜尋查詢。
您可以在下列連結中找到其他語法參考、查詢架構和範例: