Skip to content

Commit

Permalink
Add sample for sticky query sessions
Browse files Browse the repository at this point in the history
  • Loading branch information
dgetu committed Feb 16, 2024
1 parent 8e1d127 commit 41c3338
Show file tree
Hide file tree
Showing 5 changed files with 273 additions and 24 deletions.
84 changes: 84 additions & 0 deletions sdk/search/search-documents/samples-dev/stickySession.ts
Original file line number Diff line number Diff line change
@@ -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<void> {
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<Hotel> = indexClient.getSearchClient<Hotel>(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();
26 changes: 14 additions & 12 deletions sdk/search/search-documents/samples/v12-beta/javascript/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
@@ -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();
26 changes: 14 additions & 12 deletions sdk/search/search-documents/samples/v12-beta/typescript/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
@@ -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<void> {
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<Hotel> = indexClient.getSearchClient<Hotel>(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();

0 comments on commit 41c3338

Please sign in to comment.