Skip to content
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -65,4 +65,6 @@
<suppress files="com.azure.search.documents.models.VectorizableImageUrlQuery.java" checks="com.azure.tools.checkstyle.checks.EnforceFinalFieldsCheck" />
<suppress files="com.azure.search.documents.models.VectorQuery.java" checks="com.azure.tools.checkstyle.checks.EnforceFinalFieldsCheck" />
<suppress files="com.azure.search.documents.models.VectorThreshold.java" checks="com.azure.tools.checkstyle.checks.EnforceFinalFieldsCheck" />
<suppress files="com.azure.search.documents.indexes.implementation.KnowledgeAgentsImpl.java" checks="MissingJavadocMethodCheck" />
<suppress files="com.azure.search.documents.agents.implementation.KnowledgeRetrievalsImpl.java" checks="MissingJavadocMethodCheck" />
</suppressions>

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -832,10 +832,48 @@ public <T> T getDocument(String key, Class<T> modelClass) {
@ServiceMethod(returns = ReturnType.SINGLE)
public <T> Response<T> getDocumentWithResponse(String key, Class<T> modelClass, List<String> selectedFields,
Context context) {
return getDocumentWithResponse(key, modelClass, selectedFields, null, context);
}

/**
* Retrieves a document from the Azure AI Search index.
* <p>
* View <a href="https://docs.microsoft.com/rest/api/searchservice/Naming-rules">naming rules</a> for guidelines on
* constructing valid document keys.
*
* <p><strong>Code Sample</strong></p>
*
* <p> Get dynamic SearchDocument. </p>
*
* <!-- src_embed com.azure.search.documents.SearchClient.getDocumentWithResponse#String-Class-List-Context -->
* <pre>
* Response&lt;SearchDocument&gt; resultResponse = SEARCH_CLIENT.getDocumentWithResponse&#40;&quot;hotelId&quot;,
* SearchDocument.class, null, new Context&#40;KEY_1, VALUE_1&#41;&#41;;
* System.out.println&#40;&quot;The status code of the response is &quot; + resultResponse.getStatusCode&#40;&#41;&#41;;
* for &#40;Map.Entry&lt;String, Object&gt; keyValuePair : resultResponse.getValue&#40;&#41;.entrySet&#40;&#41;&#41; &#123;
* System.out.printf&#40;&quot;Document key %s, Document value %s&quot;, keyValuePair.getKey&#40;&#41;, keyValuePair.getValue&#40;&#41;&#41;;
* &#125;
* </pre>
* <!-- end com.azure.search.documents.SearchClient.getDocumentWithResponse#String-Class-List-Context -->
*
* @param <T> Convert document to the generic type.
* @param key The key of the document to retrieve.
* @param modelClass The model class converts to.
* @param selectedFields List of field names to retrieve for the document; Any field not retrieved will have null or
* default as its corresponding property value in the returned object.
* @param querySourceAuthorization Token identifying the user for which the query is being executed.
* This token is used to enforce security restrictions on documents.
* @param context additional context that is passed through the Http pipeline during the service call
* @return response containing a document object
* @see <a href="https://docs.microsoft.com/rest/api/searchservice/Lookup-Document">Lookup document</a>
*/
@ServiceMethod(returns = ReturnType.SINGLE)
public <T> Response<T> getDocumentWithResponse(String key, Class<T> modelClass, List<String> selectedFields,
String querySourceAuthorization, Context context) {

try {
Response<Map<String, Object>> response
= restClient.getDocuments().getWithResponse(key, selectedFields, null, context);
Response<Map<String, Object>> response = restClient.getDocuments()
.getWithResponse(key, selectedFields, querySourceAuthorization, null, context);

return new SimpleResponse<>(response, serializer
.deserializeFromBytes(serializer.serializeToBytes(response.getValue()), createInstance(modelClass)));
Expand Down Expand Up @@ -1001,17 +1039,78 @@ public SearchPagedIterable search(String searchText) {
*/
@ServiceMethod(returns = ReturnType.COLLECTION)
public SearchPagedIterable search(String searchText, SearchOptions searchOptions, Context context) {
return search(searchText, searchOptions, null, context);
}

/**
* Searches for documents in the Azure AI Search index.
* <p>
* If {@code searchText} is set to null or {@code "*"} all documents will be matched, see
* <a href="https://docs.microsoft.com/rest/api/searchservice/Simple-query-syntax-in-Azure-Search">simple query
* syntax in Azure AI Search</a> for more information about search query syntax.
* <p>
* The {@link SearchPagedIterable} will iterate through search result pages until all search results are returned.
* Each page is determined by the {@code $skip} and {@code $top} values and the Search service has a limit on the
* number of documents that can be skipped, more information about the {@code $skip} limit can be found at
* <a href="https://learn.microsoft.com/rest/api/searchservice/search-documents">Search Documents REST API</a> and
* reading the {@code $skip} description. If the total number of results exceeds the {@code $skip} limit the
* {@link SearchPagedIterable} won't prevent you from exceeding the {@code $skip} limit. To prevent exceeding the
* limit you can track the number of documents returned and stop requesting new pages when the limit is reached.
*
* <p><strong>Code Sample</strong></p>
*
* <p> Search text from documents in service with option. </p>
*
* <!-- src_embed com.azure.search.documents.SearchClient.search#String-SearchOptions-Context -->
* <pre>
* SearchPagedIterable searchPagedIterable = SEARCH_CLIENT.search&#40;&quot;searchText&quot;,
* new SearchOptions&#40;&#41;.setOrderBy&#40;&quot;hotelId desc&quot;&#41;, new Context&#40;KEY_1, VALUE_1&#41;&#41;;
* System.out.printf&#40;&quot;There are around %d results.&quot;, searchPagedIterable.getTotalCount&#40;&#41;&#41;;
*
* long numberOfDocumentsReturned = 0;
* for &#40;SearchPagedResponse resultResponse: searchPagedIterable.iterableByPage&#40;&#41;&#41; &#123;
* System.out.println&#40;&quot;The status code of the response is &quot; + resultResponse.getStatusCode&#40;&#41;&#41;;
* numberOfDocumentsReturned += resultResponse.getValue&#40;&#41;.size&#40;&#41;;
* resultResponse.getValue&#40;&#41;.forEach&#40;searchResult -&gt; &#123;
* for &#40;Map.Entry&lt;String, Object&gt; keyValuePair: searchResult
* .getDocument&#40;SearchDocument.class&#41;.entrySet&#40;&#41;&#41; &#123;
* System.out.printf&#40;&quot;Document key %s, document value %s&quot;, keyValuePair.getKey&#40;&#41;,
* keyValuePair.getValue&#40;&#41;&#41;;
* &#125;
* &#125;&#41;;
*
* if &#40;numberOfDocumentsReturned &gt;= SEARCH_SKIP_LIMIT&#41; &#123;
* &#47;&#47; Reached the $skip limit, stop requesting more documents.
* break;
* &#125;
* &#125;
* </pre>
* <!-- end com.azure.search.documents.SearchClient.search#String-SearchOptions-Context -->
*
* @param searchText A full-text search query expression.
* @param searchOptions Parameters to further refine the search query
* @param querySourceAuthorization Token identifying the user for which the query is being executed.
* This token is used to enforce security restrictions on documents.
* @param context additional context that is passed through the Http pipeline during the service call
* @return A {@link SearchPagedIterable} that iterates over {@link SearchResult} objects and provides access to the
* {@link SearchPagedResponse} object for each page containing HTTP response and count, facet, and coverage
* information.
* @see <a href="https://docs.microsoft.com/rest/api/searchservice/Search-Documents">Search documents</a>
*/
@ServiceMethod(returns = ReturnType.COLLECTION)
public SearchPagedIterable search(String searchText, SearchOptions searchOptions, String querySourceAuthorization,
Context context) {
SearchRequest request = createSearchRequest(searchText, searchOptions);
// The firstPageResponse shared among all functional calls below.
// Do not initial new instance directly in func call.
final SearchFirstPageResponseWrapper firstPageResponseWrapper = new SearchFirstPageResponseWrapper();
Function<String, SearchPagedResponse> func
= continuationToken -> search(request, continuationToken, firstPageResponseWrapper, context);
Function<String, SearchPagedResponse> func = continuationToken -> search(request, continuationToken,
firstPageResponseWrapper, querySourceAuthorization, context);
return new SearchPagedIterable(() -> func.apply(null), func);
}

private SearchPagedResponse search(SearchRequest request, String continuationToken,
SearchFirstPageResponseWrapper firstPageResponseWrapper, Context context) {
SearchFirstPageResponseWrapper firstPageResponseWrapper, String querySourceAuthorization, Context context) {
if (continuationToken == null && firstPageResponseWrapper.getFirstPageResponse() != null) {
return firstPageResponseWrapper.getFirstPageResponse();
}
Expand All @@ -1020,8 +1119,8 @@ private SearchPagedResponse search(SearchRequest request, String continuationTok
: SearchContinuationToken.deserializeToken(serviceVersion.getVersion(), continuationToken);

return Utility.executeRestCallWithExceptionHandling(() -> {
Response<SearchDocumentsResult> response
= restClient.getDocuments().searchPostWithResponse(requestToUse, null, context);
Response<SearchDocumentsResult> response = restClient.getDocuments()
.searchPostWithResponse(requestToUse, querySourceAuthorization, null, context);
SearchDocumentsResult result = response.getValue();
SearchPagedResponse page
= new SearchPagedResponse(new SimpleResponse<>(response, getSearchResults(result, serializer)),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
package com.azure.search.documents.agents;

import static com.azure.core.util.FluxUtil.monoError;
import static com.azure.core.util.FluxUtil.withContext;

import com.azure.core.annotation.ReturnType;
import com.azure.core.annotation.ServiceClient;
import com.azure.core.annotation.ServiceMethod;
import com.azure.core.http.HttpPipeline;
import com.azure.core.http.rest.Response;
import com.azure.core.util.Context;
import com.azure.core.util.logging.ClientLogger;
import com.azure.search.documents.agents.implementation.KnowledgeAgentRetrievalClientImpl;
import com.azure.search.documents.agents.implementation.KnowledgeRetrievalsImpl;
import com.azure.search.documents.agents.models.KnowledgeAgentRetrievalRequest;
import com.azure.search.documents.agents.models.KnowledgeAgentRetrievalResponse;
import com.azure.search.documents.implementation.util.MappingUtils;

import reactor.core.publisher.Mono;

/**
* This class provides an asynchronous client for interacting with Azure AI Search Knowledge Agents, enabling retrieval of knowledge and data from various configured backing stores.
*
* <h2>Overview</h2>
* <p>
* The {@code SearchKnowledgeAgentAsyncClient} exposes asynchronous APIs for sending retrieval requests to a knowledge agent in Azure AI Search. The agent can aggregate and return relevant data from multiple sources, such as Azure AI Search indexes, vector stores, and other knowledge bases configured in your Azure AI Search instance.
* </p>
*
* <h2>Getting Started</h2>
* <p>
* Instances of this client are created via the {@link SearchKnowledgeAgentClientBuilder}, which supports fluent configuration of credentials, endpoints, agent names, API versions, and other client options. Authentication can be performed using either an API key or Azure Active Directory credentials. The builder allows you to specify all required parameters for your scenario.
* </p>
*
* <h2>Thread Safety</h2>
* <p>
* This client is thread-safe and intended to be shared and reused across threads. Client instances are immutable and do not maintain any mutable state.
* </p>
*
* <h2>Additional Information</h2>
* <ul>
* <li>For more information about Azure AI Search Knowledge Agents, see the Azure documentation.</li>
* <li>For authentication details, see the Azure AI Search security documentation.</li>
* <li>For Azure SDK for Java guidelines, see the <a href="https://azure.github.io/azure-sdk/java_introduction.html">Azure SDK for Java Introduction</a>.</li>
* </ul>
*
* @see SearchKnowledgeAgentClientBuilder
* @see SearchKnowledgeAgentClient
* @see com.azure.search.documents.agents
*/
@ServiceClient(builder = SearchKnowledgeAgentClientBuilder.class, isAsync = true)
public final class SearchKnowledgeAgentAsyncClient {
private static final ClientLogger LOGGER = new ClientLogger(SearchKnowledgeAgentAsyncClient.class);

private final String endpoint;
private final String agentName;
private final String apiVersion;
private final HttpPipeline httpPipeline;
private final KnowledgeAgentRetrievalClientImpl impl;
private final KnowledgeRetrievalsImpl retrievals;

/**
* Package-private constructor to be used by {@link SearchKnowledgeAgentClientBuilder}.
*/
SearchKnowledgeAgentAsyncClient(String endpoint, String agentName, String apiVersion, HttpPipeline httpPipeline) {
this.endpoint = endpoint;
this.agentName = agentName;
this.apiVersion = apiVersion;
this.httpPipeline = httpPipeline;
this.impl = new KnowledgeAgentRetrievalClientImpl(httpPipeline, endpoint, agentName, apiVersion);
this.retrievals = impl.getKnowledgeRetrievals();
}

/**
* Gets the endpoint for the Azure AI Search service.
*
* @return the endpoint value.
*/
public String getEndpoint() {
return this.endpoint;
}

/**
* Gets the agent name.
*
* @return the agentName value.
*/
public String getAgentName() {
return this.agentName;
}

/**
* Gets the API version.
*
* @return the apiVersion value.
*/
public String getApiVersion() {
return this.apiVersion;
}

/**
* Gets the {@link HttpPipeline} powering this client.
*
* @return the pipeline.
*/
public HttpPipeline getHttpPipeline() {
return this.httpPipeline;
}

/**
* Asynchronously retrieves relevant data from backing stores.
*
* @param retrievalRequest The retrieval request to process.
* @param xMsQuerySourceAuthorization Token identifying the user for which the query is being executed.
* @return a {@link Mono} emitting the output contract for the retrieval response.
*/
@ServiceMethod(returns = ReturnType.SINGLE)
public Mono<KnowledgeAgentRetrievalResponse> retrieve(KnowledgeAgentRetrievalRequest retrievalRequest,
String xMsQuerySourceAuthorization) {
return retrievals.retrieveAsync(retrievalRequest, xMsQuerySourceAuthorization, null);
}

/**
* Asynchronously retrieves relevant data from backing stores, with a full HTTP response.
*
* @param retrievalRequest The retrieval request to process.
* @param xMsQuerySourceAuthorization Token identifying the user for which the query is being executed.
* @return a {@link Mono} emitting the output contract for the retrieval response along with {@link Response}.
*/
@ServiceMethod(returns = ReturnType.SINGLE)
public Mono<Response<KnowledgeAgentRetrievalResponse>>
retrieveWithResponse(KnowledgeAgentRetrievalRequest retrievalRequest, String xMsQuerySourceAuthorization) {
return withContext(context -> retrieveWithResponse(retrievalRequest, xMsQuerySourceAuthorization, context));
}

Mono<Response<KnowledgeAgentRetrievalResponse>> retrieveWithResponse(
KnowledgeAgentRetrievalRequest retrievalRequest, String xMsQuerySourceAuthorization, Context context) {
try {
return retrievals.retrieveWithResponseAsync(retrievalRequest, xMsQuerySourceAuthorization, null, context)
.onErrorMap(MappingUtils::exceptionMapper);
} catch (RuntimeException e) {
return monoError(LOGGER, e);
}
}
}
Loading
Loading