From fe1e6de3b1e7e1329e4ea45c91e491cdb05d146d Mon Sep 17 00:00:00 2001 From: Daniel Getu Date: Wed, 14 Feb 2024 17:25:02 +0000 Subject: [PATCH] Add sample for sticky query sessions --- .../samples-dev/stickySession.ts | 84 +++++++++++++++++++ .../samples/v12-beta/javascript/README.md | 26 +++--- .../v12-beta/javascript/stickySession.js | 77 +++++++++++++++++ .../samples/v12-beta/typescript/README.md | 26 +++--- .../v12-beta/typescript/src/stickySession.ts | 84 +++++++++++++++++++ 5 files changed, 273 insertions(+), 24 deletions(-) create mode 100644 sdk/search/search-documents/samples-dev/stickySession.ts create mode 100644 sdk/search/search-documents/samples/v12-beta/javascript/stickySession.js create mode 100644 sdk/search/search-documents/samples/v12-beta/typescript/src/stickySession.ts diff --git a/sdk/search/search-documents/samples-dev/stickySession.ts b/sdk/search/search-documents/samples-dev/stickySession.ts new file mode 100644 index 000000000000..a56a9b1548e7 --- /dev/null +++ b/sdk/search/search-documents/samples-dev/stickySession.ts @@ -0,0 +1,84 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +/** + * @summary Demonstrates user sticky sessions, a way to reduce inconsistent behavior by targeting a + * single replica. + */ + +import { + AzureKeyCredential, + SearchClient, + SearchIndexClient, + odata, +} from "@azure/search-documents"; +import { createIndex, WAIT_TIME, delay } from "./setup"; +import { Hotel } from "./interfaces"; + +import * as dotenv from "dotenv"; +dotenv.config(); + +/** + * If you're querying a replicated index, Azure AI Search may target any replica with your queries. + * As these replicas may not be in a consistent state, the service may appear to have inconsistent + * states between distinct queries. To avoid this, you can use a sticky session. A sticky session + * is used to indicate to the Azure AI Search service that you'd like all requests with the same + * `sessionId` to be directed to the same replica. The service will then make a best effort to do + * so. + * + * Please see the + * {@link https://learn.microsoft.com/en-us/azure/search/index-similarity-and-scoring#scoring-statistics-and-sticky-sessions | documentation} + * for more information. + */ +const endpoint = process.env.ENDPOINT || ""; +const apiKey = process.env.SEARCH_API_ADMIN_KEY || ""; +const TEST_INDEX_NAME = "example-index-sample-3"; + +async function main(): Promise { + if (!endpoint || !apiKey) { + console.error( + "Be sure to set valid values for `endpoint` and `apiKey` with proper authorization.", + ); + return; + } + + const credential = new AzureKeyCredential(apiKey); + const indexClient: SearchIndexClient = new SearchIndexClient(endpoint, credential); + const searchClient: SearchClient = indexClient.getSearchClient(TEST_INDEX_NAME); + + // The session id is defined by the user. + const sessionId = "session1"; + + try { + await createIndex(indexClient, TEST_INDEX_NAME); + await delay(WAIT_TIME); + + // The service will make a best effort attempt to direct these queries to the same replica. As + // this overrides load balancing, excessive use of the same `sessionId` may result in + // performance degradation. Be sure to use a distinct `sessionId` for each sticky session. + const ratingQueries = [2, 4]; + for (const rating of ratingQueries) { + const response = await searchClient.search("*", { + filter: odata`rating ge ${rating}`, + sessionId, + }); + + const hotelNames = []; + for await (const result of response.results) { + const hotelName = result.document.hotelName; + if (typeof hotelName === "string") { + hotelNames.push(hotelName); + } + } + + if (hotelNames.length) { + console.log(`Hotels with at least a rating of ${rating}:`); + hotelNames.forEach(console.log); + } + } + } finally { + await indexClient.deleteIndex(TEST_INDEX_NAME); + } +} + +main(); diff --git a/sdk/search/search-documents/samples/v12-beta/javascript/README.md b/sdk/search/search-documents/samples/v12-beta/javascript/README.md index 167160ba32eb..0b8fcfa0bb45 100644 --- a/sdk/search/search-documents/samples/v12-beta/javascript/README.md +++ b/sdk/search/search-documents/samples/v12-beta/javascript/README.md @@ -13,18 +13,19 @@ urlFragment: search-documents-javascript-beta These sample programs show how to use the JavaScript client libraries for Azure Search Documents in some common scenarios. -| **File Name** | **Description** | -| ------------------------------------------------------------------- | ---------------------------------------------------------------------------- | -| [bufferedSenderAutoFlushSize.js][bufferedsenderautoflushsize] | Demonstrates the SearchIndexingBufferedSender with Autoflush based on size. | -| [bufferedSenderAutoFlushTimer.js][bufferedsenderautoflushtimer] | Demonstrates the SearchIndexingBufferedSender with Autoflush based on timer. | -| [bufferedSenderManualFlush.js][bufferedsendermanualflush] | Demonstrates the SearchIndexingBufferedSender with Manual Flush. | -| [dataSourceConnectionOperations.js][datasourceconnectionoperations] | Demonstrates the DataSource Connection Operations. | -| [indexOperations.js][indexoperations] | Demonstrates the Index Operations. | -| [indexerOperations.js][indexeroperations] | Demonstrates the Indexer Operations. | -| [searchClientOperations.js][searchclientoperations] | Demonstrates the SearchClient. | -| [skillSetOperations.js][skillsetoperations] | Demonstrates the Skillset Operations. | -| [synonymMapOperations.js][synonymmapoperations] | Demonstrates the SynonymMap Operations. | -| [vectorSearch.js][vectorsearch] | Demonstrates vector search | +| **File Name** | **Description** | +| ------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- | +| [bufferedSenderAutoFlushSize.js][bufferedsenderautoflushsize] | Demonstrates the SearchIndexingBufferedSender with Autoflush based on size. | +| [bufferedSenderAutoFlushTimer.js][bufferedsenderautoflushtimer] | Demonstrates the SearchIndexingBufferedSender with Autoflush based on timer. | +| [bufferedSenderManualFlush.js][bufferedsendermanualflush] | Demonstrates the SearchIndexingBufferedSender with Manual Flush. | +| [dataSourceConnectionOperations.js][datasourceconnectionoperations] | Demonstrates the DataSource Connection Operations. | +| [indexOperations.js][indexoperations] | Demonstrates the Index Operations. | +| [indexerOperations.js][indexeroperations] | Demonstrates the Indexer Operations. | +| [searchClientOperations.js][searchclientoperations] | Demonstrates the SearchClient. | +| [skillSetOperations.js][skillsetoperations] | Demonstrates the Skillset Operations. | +| [stickySession.js][stickysession] | Demonstrates user sticky sessions, a way to reduce inconsistent behavior by targeting a single replica. | +| [synonymMapOperations.js][synonymmapoperations] | Demonstrates the SynonymMap Operations. | +| [vectorSearch.js][vectorsearch] | Demonstrates vector search | ## Prerequisites @@ -74,6 +75,7 @@ Take a look at our [API Documentation][apiref] for more information about the AP [indexeroperations]: https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/search/search-documents/samples/v12-beta/javascript/indexerOperations.js [searchclientoperations]: https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/search/search-documents/samples/v12-beta/javascript/searchClientOperations.js [skillsetoperations]: https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/search/search-documents/samples/v12-beta/javascript/skillSetOperations.js +[stickysession]: https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/search/search-documents/samples/v12-beta/javascript/stickySession.js [synonymmapoperations]: https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/search/search-documents/samples/v12-beta/javascript/synonymMapOperations.js [vectorsearch]: https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/search/search-documents/samples/v12-beta/javascript/vectorSearch.js [apiref]: https://docs.microsoft.com/javascript/api/@azure/search-documents diff --git a/sdk/search/search-documents/samples/v12-beta/javascript/stickySession.js b/sdk/search/search-documents/samples/v12-beta/javascript/stickySession.js new file mode 100644 index 000000000000..8fb32332f773 --- /dev/null +++ b/sdk/search/search-documents/samples/v12-beta/javascript/stickySession.js @@ -0,0 +1,77 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +/** + * @summary Demonstrates user sticky sessions, a way to reduce inconsistent behavior by targeting a + * single replica. + */ + +const { AzureKeyCredential, SearchIndexClient, odata } = require("@azure/search-documents"); +const { createIndex, WAIT_TIME, delay } = require("./setup"); + +require("dotenv").config(); + +/** + * If you're querying a replicated index, Azure AI Search may target any replica with your queries. + * As these replicas may not be in a consistent state, the service may appear to have inconsistent + * states between distinct queries. To avoid this, you can use a sticky session. A sticky session + * is used to indicate to the Azure AI Search service that you'd like all requests with the same + * `sessionId` to be directed to the same replica. The service will then make a best effort to do + * so. + * + * Please see the + * {@link https://learn.microsoft.com/en-us/azure/search/index-similarity-and-scoring#scoring-statistics-and-sticky-sessions | documentation} + * for more information. + */ +const endpoint = process.env.ENDPOINT || ""; +const apiKey = process.env.SEARCH_API_ADMIN_KEY || ""; +const TEST_INDEX_NAME = "example-index-sample-3"; + +async function main() { + if (!endpoint || !apiKey) { + console.error( + "Be sure to set valid values for `endpoint` and `apiKey` with proper authorization.", + ); + return; + } + + const credential = new AzureKeyCredential(apiKey); + const indexClient = new SearchIndexClient(endpoint, credential); + const searchClient = indexClient.getSearchClient(TEST_INDEX_NAME); + + // The session id is defined by the user. + const sessionId = "session1"; + + try { + await createIndex(indexClient, TEST_INDEX_NAME); + await delay(WAIT_TIME); + + // The service will make a best effort attempt to direct these queries to the same replica. As + // this overrides load balancing, excessive use of the same `sessionId` may result in + // performance degradation. Be sure to use a distinct `sessionId` for each sticky session. + const ratingQueries = [2, 4]; + for (const rating of ratingQueries) { + const response = await searchClient.search("*", { + filter: odata`rating ge ${rating}`, + sessionId, + }); + + const hotelNames = []; + for await (const result of response.results) { + const hotelName = result.document.hotelName; + if (typeof hotelName === "string") { + hotelNames.push(hotelName); + } + } + + if (hotelNames.length) { + console.log(`Hotels with at least a rating of ${rating}:`); + hotelNames.forEach(console.log); + } + } + } finally { + await indexClient.deleteIndex(TEST_INDEX_NAME); + } +} + +main(); diff --git a/sdk/search/search-documents/samples/v12-beta/typescript/README.md b/sdk/search/search-documents/samples/v12-beta/typescript/README.md index da0592d5a261..9bb632d3e01c 100644 --- a/sdk/search/search-documents/samples/v12-beta/typescript/README.md +++ b/sdk/search/search-documents/samples/v12-beta/typescript/README.md @@ -13,18 +13,19 @@ urlFragment: search-documents-typescript-beta These sample programs show how to use the TypeScript client libraries for Azure Search Documents in some common scenarios. -| **File Name** | **Description** | -| ------------------------------------------------------------------- | ---------------------------------------------------------------------------- | -| [bufferedSenderAutoFlushSize.ts][bufferedsenderautoflushsize] | Demonstrates the SearchIndexingBufferedSender with Autoflush based on size. | -| [bufferedSenderAutoFlushTimer.ts][bufferedsenderautoflushtimer] | Demonstrates the SearchIndexingBufferedSender with Autoflush based on timer. | -| [bufferedSenderManualFlush.ts][bufferedsendermanualflush] | Demonstrates the SearchIndexingBufferedSender with Manual Flush. | -| [dataSourceConnectionOperations.ts][datasourceconnectionoperations] | Demonstrates the DataSource Connection Operations. | -| [indexOperations.ts][indexoperations] | Demonstrates the Index Operations. | -| [indexerOperations.ts][indexeroperations] | Demonstrates the Indexer Operations. | -| [searchClientOperations.ts][searchclientoperations] | Demonstrates the SearchClient. | -| [skillSetOperations.ts][skillsetoperations] | Demonstrates the Skillset Operations. | -| [synonymMapOperations.ts][synonymmapoperations] | Demonstrates the SynonymMap Operations. | -| [vectorSearch.ts][vectorsearch] | Demonstrates vector search | +| **File Name** | **Description** | +| ------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- | +| [bufferedSenderAutoFlushSize.ts][bufferedsenderautoflushsize] | Demonstrates the SearchIndexingBufferedSender with Autoflush based on size. | +| [bufferedSenderAutoFlushTimer.ts][bufferedsenderautoflushtimer] | Demonstrates the SearchIndexingBufferedSender with Autoflush based on timer. | +| [bufferedSenderManualFlush.ts][bufferedsendermanualflush] | Demonstrates the SearchIndexingBufferedSender with Manual Flush. | +| [dataSourceConnectionOperations.ts][datasourceconnectionoperations] | Demonstrates the DataSource Connection Operations. | +| [indexOperations.ts][indexoperations] | Demonstrates the Index Operations. | +| [indexerOperations.ts][indexeroperations] | Demonstrates the Indexer Operations. | +| [searchClientOperations.ts][searchclientoperations] | Demonstrates the SearchClient. | +| [skillSetOperations.ts][skillsetoperations] | Demonstrates the Skillset Operations. | +| [stickySession.ts][stickysession] | Demonstrates user sticky sessions, a way to reduce inconsistent behavior by targeting a single replica. | +| [synonymMapOperations.ts][synonymmapoperations] | Demonstrates the SynonymMap Operations. | +| [vectorSearch.ts][vectorsearch] | Demonstrates vector search | ## Prerequisites @@ -86,6 +87,7 @@ Take a look at our [API Documentation][apiref] for more information about the AP [indexeroperations]: https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/search/search-documents/samples/v12-beta/typescript/src/indexerOperations.ts [searchclientoperations]: https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/search/search-documents/samples/v12-beta/typescript/src/searchClientOperations.ts [skillsetoperations]: https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/search/search-documents/samples/v12-beta/typescript/src/skillSetOperations.ts +[stickysession]: https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/search/search-documents/samples/v12-beta/typescript/src/stickySession.ts [synonymmapoperations]: https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/search/search-documents/samples/v12-beta/typescript/src/synonymMapOperations.ts [vectorsearch]: https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/search/search-documents/samples/v12-beta/typescript/src/vectorSearch.ts [apiref]: https://docs.microsoft.com/javascript/api/@azure/search-documents diff --git a/sdk/search/search-documents/samples/v12-beta/typescript/src/stickySession.ts b/sdk/search/search-documents/samples/v12-beta/typescript/src/stickySession.ts new file mode 100644 index 000000000000..a56a9b1548e7 --- /dev/null +++ b/sdk/search/search-documents/samples/v12-beta/typescript/src/stickySession.ts @@ -0,0 +1,84 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +/** + * @summary Demonstrates user sticky sessions, a way to reduce inconsistent behavior by targeting a + * single replica. + */ + +import { + AzureKeyCredential, + SearchClient, + SearchIndexClient, + odata, +} from "@azure/search-documents"; +import { createIndex, WAIT_TIME, delay } from "./setup"; +import { Hotel } from "./interfaces"; + +import * as dotenv from "dotenv"; +dotenv.config(); + +/** + * If you're querying a replicated index, Azure AI Search may target any replica with your queries. + * As these replicas may not be in a consistent state, the service may appear to have inconsistent + * states between distinct queries. To avoid this, you can use a sticky session. A sticky session + * is used to indicate to the Azure AI Search service that you'd like all requests with the same + * `sessionId` to be directed to the same replica. The service will then make a best effort to do + * so. + * + * Please see the + * {@link https://learn.microsoft.com/en-us/azure/search/index-similarity-and-scoring#scoring-statistics-and-sticky-sessions | documentation} + * for more information. + */ +const endpoint = process.env.ENDPOINT || ""; +const apiKey = process.env.SEARCH_API_ADMIN_KEY || ""; +const TEST_INDEX_NAME = "example-index-sample-3"; + +async function main(): Promise { + if (!endpoint || !apiKey) { + console.error( + "Be sure to set valid values for `endpoint` and `apiKey` with proper authorization.", + ); + return; + } + + const credential = new AzureKeyCredential(apiKey); + const indexClient: SearchIndexClient = new SearchIndexClient(endpoint, credential); + const searchClient: SearchClient = indexClient.getSearchClient(TEST_INDEX_NAME); + + // The session id is defined by the user. + const sessionId = "session1"; + + try { + await createIndex(indexClient, TEST_INDEX_NAME); + await delay(WAIT_TIME); + + // The service will make a best effort attempt to direct these queries to the same replica. As + // this overrides load balancing, excessive use of the same `sessionId` may result in + // performance degradation. Be sure to use a distinct `sessionId` for each sticky session. + const ratingQueries = [2, 4]; + for (const rating of ratingQueries) { + const response = await searchClient.search("*", { + filter: odata`rating ge ${rating}`, + sessionId, + }); + + const hotelNames = []; + for await (const result of response.results) { + const hotelName = result.document.hotelName; + if (typeof hotelName === "string") { + hotelNames.push(hotelName); + } + } + + if (hotelNames.length) { + console.log(`Hotels with at least a rating of ${rating}:`); + hotelNames.forEach(console.log); + } + } + } finally { + await indexClient.deleteIndex(TEST_INDEX_NAME); + } +} + +main();