// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
//
// Code generated by Microsoft (R) AutoRest Code Generator.
// Changes may cause incorrect behavior and will be lost if the code is regenerated.

package com.azure.search.documents.implementation.models;

import com.azure.core.annotation.Fluent;
import com.azure.json.JsonReader;
import com.azure.json.JsonSerializable;
import com.azure.json.JsonToken;
import com.azure.json.JsonWriter;
import com.azure.search.documents.models.QueryDebugMode;
import com.azure.search.documents.models.QueryLanguage;
import com.azure.search.documents.models.QuerySpellerType;
import com.azure.search.documents.models.QueryType;
import com.azure.search.documents.models.ScoringStatistics;
import com.azure.search.documents.models.SearchMode;
import com.azure.search.documents.models.SearchQueryVector;
import com.azure.search.documents.models.SemanticErrorHandling;
import java.io.IOException;
import java.util.List;
import java.util.Objects;

/** Parameters for filtering, sorting, faceting, paging, and other search query behaviors. */
@Fluent
public final class SearchRequest implements JsonSerializable<SearchRequest> {
    /*
     * A value that specifies whether to fetch the total count of results. Default is false. Setting this value to true
     * may have a performance impact. Note that the count returned is an approximation.
     */
    private Boolean includeTotalResultCount;

    /*
     * The list of facet expressions to apply to the search query. Each facet expression contains a field name,
     * optionally followed by a comma-separated list of name:value pairs.
     */
    private List<String> facets;

    /*
     * The OData $filter expression to apply to the search query.
     */
    private String filter;

    /*
     * The comma-separated list of field names to use for hit highlights. Only searchable fields can be used for hit
     * highlighting.
     */
    private String highlightFields;

    /*
     * A string tag that is appended to hit highlights. Must be set with highlightPreTag. Default is &lt;/em&gt;.
     */
    private String highlightPostTag;

    /*
     * A string tag that is prepended to hit highlights. Must be set with highlightPostTag. Default is &lt;em&gt;.
     */
    private String highlightPreTag;

    /*
     * A number between 0 and 100 indicating the percentage of the index that must be covered by a search query in
     * order for the query to be reported as a success. This parameter can be useful for ensuring search availability
     * even for services with only one replica. The default is 100.
     */
    private Double minimumCoverage;

    /*
     * The comma-separated list of OData $orderby expressions by which to sort the results. Each expression can be
     * either a field name or a call to either the geo.distance() or the search.score() functions. Each expression can
     * be followed by asc to indicate ascending, or desc to indicate descending. The default is ascending order. Ties
     * will be broken by the match scores of documents. If no $orderby is specified, the default sort order is
     * descending by document match score. There can be at most 32 $orderby clauses.
     */
    private String orderBy;

    /*
     * A value that specifies the syntax of the search query. The default is 'simple'. Use 'full' if your query uses
     * the Lucene query syntax.
     */
    private QueryType queryType;

    /*
     * A value that specifies whether we want to calculate scoring statistics (such as document frequency) globally for
     * more consistent scoring, or locally, for lower latency. The default is 'local'. Use 'global' to aggregate
     * scoring statistics globally before scoring. Using global scoring statistics can increase latency of search
     * queries.
     */
    private ScoringStatistics scoringStatistics;

    /*
     * A value to be used to create a sticky session, which can help getting more consistent results. As long as the
     * same sessionId is used, a best-effort attempt will be made to target the same replica set. Be wary that reusing
     * the same sessionID values repeatedly can interfere with the load balancing of the requests across replicas and
     * adversely affect the performance of the search service. The value used as sessionId cannot start with a '_'
     * character.
     */
    private String sessionId;

    /*
     * The list of parameter values to be used in scoring functions (for example, referencePointParameter) using the
     * format name-values. For example, if the scoring profile defines a function with a parameter called 'mylocation'
     * the parameter string would be "mylocation--122.2,44.8" (without the quotes).
     */
    private List<String> scoringParameters;

    /*
     * The name of a scoring profile to evaluate match scores for matching documents in order to sort the results.
     */
    private String scoringProfile;

    /*
     * The name of a semantic configuration that will be used when processing documents for queries of type semantic.
     */
    private String semanticConfiguration;

    /*
     * Allows the user to choose whether a semantic call should fail completely (default / current behavior), or to
     * return partial results.
     */
    private SemanticErrorHandling semanticErrorHandling;

    /*
     * Allows the user to set an upper bound on the amount of time it takes for semantic enrichment to finish
     * processing before the request fails.
     */
    private Integer semanticMaxWaitInMilliseconds;

    /*
     * Enables a debugging tool that can be used to further explore your Semantic search results.
     */
    private QueryDebugMode debug;

    /*
     * A full-text search query expression; Use "*" or omit this parameter to match all documents.
     */
    private String searchText;

    /*
     * The comma-separated list of field names to which to scope the full-text search. When using fielded search
     * (fieldName:searchExpression) in a full Lucene query, the field names of each fielded search expression take
     * precedence over any field names listed in this parameter.
     */
    private String searchFields;

    /*
     * A value that specifies whether any or all of the search terms must be matched in order to count the document as
     * a match.
     */
    private SearchMode searchMode;

    /*
     * A value that specifies the language of the search query.
     */
    private QueryLanguage queryLanguage;

    /*
     * A value that specified the type of the speller to use to spell-correct individual search query terms.
     */
    private QuerySpellerType speller;

    /*
     * This parameter is only valid if the query type is 'semantic'. If set, the query returns answers extracted from
     * key passages in the highest ranked documents. The number of answers returned can be configured by appending the
     * pipe character '|' followed by the 'count-<number of answers>' option after the answers parameter value, such as
     * 'extractive|count-3'. Default count is 1. The confidence threshold can be configured by appending the pipe
     * character '|' followed by the 'threshold-<confidence threshold>' option after the answers parameter value, such
     * as 'extractive|threshold-0.9'. Default threshold is 0.7.
     */
    private String answers;

    /*
     * The comma-separated list of fields to retrieve. If unspecified, all fields marked as retrievable in the schema
     * are included.
     */
    private String select;

    /*
     * The number of search results to skip. This value cannot be greater than 100,000. If you need to scan documents
     * in sequence, but cannot use skip due to this limitation, consider using orderby on a totally-ordered key and
     * filter with a range query instead.
     */
    private Integer skip;

    /*
     * The number of search results to retrieve. This can be used in conjunction with $skip to implement client-side
     * paging of search results. If results are truncated due to server-side paging, the response will include a
     * continuation token that can be used to issue another Search request for the next page of results.
     */
    private Integer top;

    /*
     * This parameter is only valid if the query type is 'semantic'. If set, the query returns captions extracted from
     * key passages in the highest ranked documents. When Captions is set to 'extractive', highlighting is enabled by
     * default, and can be configured by appending the pipe character '|' followed by the 'highlight-<true/false>'
     * option, such as 'extractive|highlight-true'. Defaults to 'None'.
     */
    private String captions;

    /*
     * The comma-separated list of field names used for semantic search.
     */
    private String semanticFields;

    /*
     * The query parameters for vector and hybrid search queries.
     */
    private SearchQueryVector vector;

    /** Creates an instance of SearchRequest class. */
    public SearchRequest() {}

    /**
     * Get the includeTotalResultCount property: A value that specifies whether to fetch the total count of results.
     * Default is false. Setting this value to true may have a performance impact. Note that the count returned is an
     * approximation.
     *
     * @return the includeTotalResultCount value.
     */
    public Boolean isIncludeTotalResultCount() {
        return this.includeTotalResultCount;
    }

    /**
     * Set the includeTotalResultCount property: A value that specifies whether to fetch the total count of results.
     * Default is false. Setting this value to true may have a performance impact. Note that the count returned is an
     * approximation.
     *
     * @param includeTotalResultCount the includeTotalResultCount value to set.
     * @return the SearchRequest object itself.
     */
    public SearchRequest setIncludeTotalResultCount(Boolean includeTotalResultCount) {
        this.includeTotalResultCount = includeTotalResultCount;
        return this;
    }

    /**
     * Get the facets property: The list of facet expressions to apply to the search query. Each facet expression
     * contains a field name, optionally followed by a comma-separated list of name:value pairs.
     *
     * @return the facets value.
     */
    public List<String> getFacets() {
        return this.facets;
    }

    /**
     * Set the facets property: The list of facet expressions to apply to the search query. Each facet expression
     * contains a field name, optionally followed by a comma-separated list of name:value pairs.
     *
     * @param facets the facets value to set.
     * @return the SearchRequest object itself.
     */
    public SearchRequest setFacets(List<String> facets) {
        this.facets = facets;
        return this;
    }

    /**
     * Get the filter property: The OData $filter expression to apply to the search query.
     *
     * @return the filter value.
     */
    public String getFilter() {
        return this.filter;
    }

    /**
     * Set the filter property: The OData $filter expression to apply to the search query.
     *
     * @param filter the filter value to set.
     * @return the SearchRequest object itself.
     */
    public SearchRequest setFilter(String filter) {
        this.filter = filter;
        return this;
    }

    /**
     * Get the highlightFields property: The comma-separated list of field names to use for hit highlights. Only
     * searchable fields can be used for hit highlighting.
     *
     * @return the highlightFields value.
     */
    public String getHighlightFields() {
        return this.highlightFields;
    }

    /**
     * Set the highlightFields property: The comma-separated list of field names to use for hit highlights. Only
     * searchable fields can be used for hit highlighting.
     *
     * @param highlightFields the highlightFields value to set.
     * @return the SearchRequest object itself.
     */
    public SearchRequest setHighlightFields(String highlightFields) {
        this.highlightFields = highlightFields;
        return this;
    }

    /**
     * Get the highlightPostTag property: A string tag that is appended to hit highlights. Must be set with
     * highlightPreTag. Default is &amp;lt;/em&amp;gt;.
     *
     * @return the highlightPostTag value.
     */
    public String getHighlightPostTag() {
        return this.highlightPostTag;
    }

    /**
     * Set the highlightPostTag property: A string tag that is appended to hit highlights. Must be set with
     * highlightPreTag. Default is &amp;lt;/em&amp;gt;.
     *
     * @param highlightPostTag the highlightPostTag value to set.
     * @return the SearchRequest object itself.
     */
    public SearchRequest setHighlightPostTag(String highlightPostTag) {
        this.highlightPostTag = highlightPostTag;
        return this;
    }

    /**
     * Get the highlightPreTag property: A string tag that is prepended to hit highlights. Must be set with
     * highlightPostTag. Default is &amp;lt;em&amp;gt;.
     *
     * @return the highlightPreTag value.
     */
    public String getHighlightPreTag() {
        return this.highlightPreTag;
    }

    /**
     * Set the highlightPreTag property: A string tag that is prepended to hit highlights. Must be set with
     * highlightPostTag. Default is &amp;lt;em&amp;gt;.
     *
     * @param highlightPreTag the highlightPreTag value to set.
     * @return the SearchRequest object itself.
     */
    public SearchRequest setHighlightPreTag(String highlightPreTag) {
        this.highlightPreTag = highlightPreTag;
        return this;
    }

    /**
     * Get the minimumCoverage property: A number between 0 and 100 indicating the percentage of the index that must be
     * covered by a search query in order for the query to be reported as a success. This parameter can be useful for
     * ensuring search availability even for services with only one replica. The default is 100.
     *
     * @return the minimumCoverage value.
     */
    public Double getMinimumCoverage() {
        return this.minimumCoverage;
    }

    /**
     * Set the minimumCoverage property: A number between 0 and 100 indicating the percentage of the index that must be
     * covered by a search query in order for the query to be reported as a success. This parameter can be useful for
     * ensuring search availability even for services with only one replica. The default is 100.
     *
     * @param minimumCoverage the minimumCoverage value to set.
     * @return the SearchRequest object itself.
     */
    public SearchRequest setMinimumCoverage(Double minimumCoverage) {
        this.minimumCoverage = minimumCoverage;
        return this;
    }

    /**
     * Get the orderBy property: The comma-separated list of OData $orderby expressions by which to sort the results.
     * Each expression can be either a field name or a call to either the geo.distance() or the search.score()
     * functions. Each expression can be followed by asc to indicate ascending, or desc to indicate descending. The
     * default is ascending order. Ties will be broken by the match scores of documents. If no $orderby is specified,
     * the default sort order is descending by document match score. There can be at most 32 $orderby clauses.
     *
     * @return the orderBy value.
     */
    public String getOrderBy() {
        return this.orderBy;
    }

    /**
     * Set the orderBy property: The comma-separated list of OData $orderby expressions by which to sort the results.
     * Each expression can be either a field name or a call to either the geo.distance() or the search.score()
     * functions. Each expression can be followed by asc to indicate ascending, or desc to indicate descending. The
     * default is ascending order. Ties will be broken by the match scores of documents. If no $orderby is specified,
     * the default sort order is descending by document match score. There can be at most 32 $orderby clauses.
     *
     * @param orderBy the orderBy value to set.
     * @return the SearchRequest object itself.
     */
    public SearchRequest setOrderBy(String orderBy) {
        this.orderBy = orderBy;
        return this;
    }

    /**
     * Get the queryType property: A value that specifies the syntax of the search query. The default is 'simple'. Use
     * 'full' if your query uses the Lucene query syntax.
     *
     * @return the queryType value.
     */
    public QueryType getQueryType() {
        return this.queryType;
    }

    /**
     * Set the queryType property: A value that specifies the syntax of the search query. The default is 'simple'. Use
     * 'full' if your query uses the Lucene query syntax.
     *
     * @param queryType the queryType value to set.
     * @return the SearchRequest object itself.
     */
    public SearchRequest setQueryType(QueryType queryType) {
        this.queryType = queryType;
        return this;
    }

    /**
     * Get the scoringStatistics property: A value that specifies whether we want to calculate scoring statistics (such
     * as document frequency) globally for more consistent scoring, or locally, for lower latency. The default is
     * 'local'. Use 'global' to aggregate scoring statistics globally before scoring. Using global scoring statistics
     * can increase latency of search queries.
     *
     * @return the scoringStatistics value.
     */
    public ScoringStatistics getScoringStatistics() {
        return this.scoringStatistics;
    }

    /**
     * Set the scoringStatistics property: A value that specifies whether we want to calculate scoring statistics (such
     * as document frequency) globally for more consistent scoring, or locally, for lower latency. The default is
     * 'local'. Use 'global' to aggregate scoring statistics globally before scoring. Using global scoring statistics
     * can increase latency of search queries.
     *
     * @param scoringStatistics the scoringStatistics value to set.
     * @return the SearchRequest object itself.
     */
    public SearchRequest setScoringStatistics(ScoringStatistics scoringStatistics) {
        this.scoringStatistics = scoringStatistics;
        return this;
    }

    /**
     * Get the sessionId property: A value to be used to create a sticky session, which can help getting more consistent
     * results. As long as the same sessionId is used, a best-effort attempt will be made to target the same replica
     * set. Be wary that reusing the same sessionID values repeatedly can interfere with the load balancing of the
     * requests across replicas and adversely affect the performance of the search service. The value used as sessionId
     * cannot start with a '_' character.
     *
     * @return the sessionId value.
     */
    public String getSessionId() {
        return this.sessionId;
    }

    /**
     * Set the sessionId property: A value to be used to create a sticky session, which can help getting more consistent
     * results. As long as the same sessionId is used, a best-effort attempt will be made to target the same replica
     * set. Be wary that reusing the same sessionID values repeatedly can interfere with the load balancing of the
     * requests across replicas and adversely affect the performance of the search service. The value used as sessionId
     * cannot start with a '_' character.
     *
     * @param sessionId the sessionId value to set.
     * @return the SearchRequest object itself.
     */
    public SearchRequest setSessionId(String sessionId) {
        this.sessionId = sessionId;
        return this;
    }

    /**
     * Get the scoringParameters property: The list of parameter values to be used in scoring functions (for example,
     * referencePointParameter) using the format name-values. For example, if the scoring profile defines a function
     * with a parameter called 'mylocation' the parameter string would be "mylocation--122.2,44.8" (without the quotes).
     *
     * @return the scoringParameters value.
     */
    public List<String> getScoringParameters() {
        return this.scoringParameters;
    }

    /**
     * Set the scoringParameters property: The list of parameter values to be used in scoring functions (for example,
     * referencePointParameter) using the format name-values. For example, if the scoring profile defines a function
     * with a parameter called 'mylocation' the parameter string would be "mylocation--122.2,44.8" (without the quotes).
     *
     * @param scoringParameters the scoringParameters value to set.
     * @return the SearchRequest object itself.
     */
    public SearchRequest setScoringParameters(List<String> scoringParameters) {
        this.scoringParameters = scoringParameters;
        return this;
    }

    /**
     * Get the scoringProfile property: The name of a scoring profile to evaluate match scores for matching documents in
     * order to sort the results.
     *
     * @return the scoringProfile value.
     */
    public String getScoringProfile() {
        return this.scoringProfile;
    }

    /**
     * Set the scoringProfile property: The name of a scoring profile to evaluate match scores for matching documents in
     * order to sort the results.
     *
     * @param scoringProfile the scoringProfile value to set.
     * @return the SearchRequest object itself.
     */
    public SearchRequest setScoringProfile(String scoringProfile) {
        this.scoringProfile = scoringProfile;
        return this;
    }

    /**
     * Get the semanticConfiguration property: The name of a semantic configuration that will be used when processing
     * documents for queries of type semantic.
     *
     * @return the semanticConfiguration value.
     */
    public String getSemanticConfiguration() {
        return this.semanticConfiguration;
    }

    /**
     * Set the semanticConfiguration property: The name of a semantic configuration that will be used when processing
     * documents for queries of type semantic.
     *
     * @param semanticConfiguration the semanticConfiguration value to set.
     * @return the SearchRequest object itself.
     */
    public SearchRequest setSemanticConfiguration(String semanticConfiguration) {
        this.semanticConfiguration = semanticConfiguration;
        return this;
    }

    /**
     * Get the semanticErrorHandling property: Allows the user to choose whether a semantic call should fail completely
     * (default / current behavior), or to return partial results.
     *
     * @return the semanticErrorHandling value.
     */
    public SemanticErrorHandling getSemanticErrorHandling() {
        return this.semanticErrorHandling;
    }

    /**
     * Set the semanticErrorHandling property: Allows the user to choose whether a semantic call should fail completely
     * (default / current behavior), or to return partial results.
     *
     * @param semanticErrorHandling the semanticErrorHandling value to set.
     * @return the SearchRequest object itself.
     */
    public SearchRequest setSemanticErrorHandling(SemanticErrorHandling semanticErrorHandling) {
        this.semanticErrorHandling = semanticErrorHandling;
        return this;
    }

    /**
     * Get the semanticMaxWaitInMilliseconds property: Allows the user to set an upper bound on the amount of time it
     * takes for semantic enrichment to finish processing before the request fails.
     *
     * @return the semanticMaxWaitInMilliseconds value.
     */
    public Integer getSemanticMaxWaitInMilliseconds() {
        return this.semanticMaxWaitInMilliseconds;
    }

    /**
     * Set the semanticMaxWaitInMilliseconds property: Allows the user to set an upper bound on the amount of time it
     * takes for semantic enrichment to finish processing before the request fails.
     *
     * @param semanticMaxWaitInMilliseconds the semanticMaxWaitInMilliseconds value to set.
     * @return the SearchRequest object itself.
     */
    public SearchRequest setSemanticMaxWaitInMilliseconds(Integer semanticMaxWaitInMilliseconds) {
        this.semanticMaxWaitInMilliseconds = semanticMaxWaitInMilliseconds;
        return this;
    }

    /**
     * Get the debug property: Enables a debugging tool that can be used to further explore your Semantic search
     * results.
     *
     * @return the debug value.
     */
    public QueryDebugMode getDebug() {
        return this.debug;
    }

    /**
     * Set the debug property: Enables a debugging tool that can be used to further explore your Semantic search
     * results.
     *
     * @param debug the debug value to set.
     * @return the SearchRequest object itself.
     */
    public SearchRequest setDebug(QueryDebugMode debug) {
        this.debug = debug;
        return this;
    }

    /**
     * Get the searchText property: A full-text search query expression; Use "*" or omit this parameter to match all
     * documents.
     *
     * @return the searchText value.
     */
    public String getSearchText() {
        return this.searchText;
    }

    /**
     * Set the searchText property: A full-text search query expression; Use "*" or omit this parameter to match all
     * documents.
     *
     * @param searchText the searchText value to set.
     * @return the SearchRequest object itself.
     */
    public SearchRequest setSearchText(String searchText) {
        this.searchText = searchText;
        return this;
    }

    /**
     * Get the searchFields property: The comma-separated list of field names to which to scope the full-text search.
     * When using fielded search (fieldName:searchExpression) in a full Lucene query, the field names of each fielded
     * search expression take precedence over any field names listed in this parameter.
     *
     * @return the searchFields value.
     */
    public String getSearchFields() {
        return this.searchFields;
    }

    /**
     * Set the searchFields property: The comma-separated list of field names to which to scope the full-text search.
     * When using fielded search (fieldName:searchExpression) in a full Lucene query, the field names of each fielded
     * search expression take precedence over any field names listed in this parameter.
     *
     * @param searchFields the searchFields value to set.
     * @return the SearchRequest object itself.
     */
    public SearchRequest setSearchFields(String searchFields) {
        this.searchFields = searchFields;
        return this;
    }

    /**
     * Get the searchMode property: A value that specifies whether any or all of the search terms must be matched in
     * order to count the document as a match.
     *
     * @return the searchMode value.
     */
    public SearchMode getSearchMode() {
        return this.searchMode;
    }

    /**
     * Set the searchMode property: A value that specifies whether any or all of the search terms must be matched in
     * order to count the document as a match.
     *
     * @param searchMode the searchMode value to set.
     * @return the SearchRequest object itself.
     */
    public SearchRequest setSearchMode(SearchMode searchMode) {
        this.searchMode = searchMode;
        return this;
    }

    /**
     * Get the queryLanguage property: A value that specifies the language of the search query.
     *
     * @return the queryLanguage value.
     */
    public QueryLanguage getQueryLanguage() {
        return this.queryLanguage;
    }

    /**
     * Set the queryLanguage property: A value that specifies the language of the search query.
     *
     * @param queryLanguage the queryLanguage value to set.
     * @return the SearchRequest object itself.
     */
    public SearchRequest setQueryLanguage(QueryLanguage queryLanguage) {
        this.queryLanguage = queryLanguage;
        return this;
    }

    /**
     * Get the speller property: A value that specified the type of the speller to use to spell-correct individual
     * search query terms.
     *
     * @return the speller value.
     */
    public QuerySpellerType getSpeller() {
        return this.speller;
    }

    /**
     * Set the speller property: A value that specified the type of the speller to use to spell-correct individual
     * search query terms.
     *
     * @param speller the speller value to set.
     * @return the SearchRequest object itself.
     */
    public SearchRequest setSpeller(QuerySpellerType speller) {
        this.speller = speller;
        return this;
    }

    /**
     * Get the answers property: This parameter is only valid if the query type is 'semantic'. If set, the query returns
     * answers extracted from key passages in the highest ranked documents. The number of answers returned can be
     * configured by appending the pipe character '|' followed by the 'count-&lt;number of answers&gt;' option after the
     * answers parameter value, such as 'extractive|count-3'. Default count is 1. The confidence threshold can be
     * configured by appending the pipe character '|' followed by the 'threshold-&lt;confidence threshold&gt;' option
     * after the answers parameter value, such as 'extractive|threshold-0.9'. Default threshold is 0.7.
     *
     * @return the answers value.
     */
    public String getAnswers() {
        return this.answers;
    }

    /**
     * Set the answers property: This parameter is only valid if the query type is 'semantic'. If set, the query returns
     * answers extracted from key passages in the highest ranked documents. The number of answers returned can be
     * configured by appending the pipe character '|' followed by the 'count-&lt;number of answers&gt;' option after the
     * answers parameter value, such as 'extractive|count-3'. Default count is 1. The confidence threshold can be
     * configured by appending the pipe character '|' followed by the 'threshold-&lt;confidence threshold&gt;' option
     * after the answers parameter value, such as 'extractive|threshold-0.9'. Default threshold is 0.7.
     *
     * @param answers the answers value to set.
     * @return the SearchRequest object itself.
     */
    public SearchRequest setAnswers(String answers) {
        this.answers = answers;
        return this;
    }

    /**
     * Get the select property: The comma-separated list of fields to retrieve. If unspecified, all fields marked as
     * retrievable in the schema are included.
     *
     * @return the select value.
     */
    public String getSelect() {
        return this.select;
    }

    /**
     * Set the select property: The comma-separated list of fields to retrieve. If unspecified, all fields marked as
     * retrievable in the schema are included.
     *
     * @param select the select value to set.
     * @return the SearchRequest object itself.
     */
    public SearchRequest setSelect(String select) {
        this.select = select;
        return this;
    }

    /**
     * Get the skip property: The number of search results to skip. This value cannot be greater than 100,000. If you
     * need to scan documents in sequence, but cannot use skip due to this limitation, consider using orderby on a
     * totally-ordered key and filter with a range query instead.
     *
     * @return the skip value.
     */
    public Integer getSkip() {
        return this.skip;
    }

    /**
     * Set the skip property: The number of search results to skip. This value cannot be greater than 100,000. If you
     * need to scan documents in sequence, but cannot use skip due to this limitation, consider using orderby on a
     * totally-ordered key and filter with a range query instead.
     *
     * @param skip the skip value to set.
     * @return the SearchRequest object itself.
     */
    public SearchRequest setSkip(Integer skip) {
        this.skip = skip;
        return this;
    }

    /**
     * Get the top property: The number of search results to retrieve. This can be used in conjunction with $skip to
     * implement client-side paging of search results. If results are truncated due to server-side paging, the response
     * will include a continuation token that can be used to issue another Search request for the next page of results.
     *
     * @return the top value.
     */
    public Integer getTop() {
        return this.top;
    }

    /**
     * Set the top property: The number of search results to retrieve. This can be used in conjunction with $skip to
     * implement client-side paging of search results. If results are truncated due to server-side paging, the response
     * will include a continuation token that can be used to issue another Search request for the next page of results.
     *
     * @param top the top value to set.
     * @return the SearchRequest object itself.
     */
    public SearchRequest setTop(Integer top) {
        this.top = top;
        return this;
    }

    /**
     * Get the captions property: This parameter is only valid if the query type is 'semantic'. If set, the query
     * returns captions extracted from key passages in the highest ranked documents. When Captions is set to
     * 'extractive', highlighting is enabled by default, and can be configured by appending the pipe character '|'
     * followed by the 'highlight-&lt;true/false&gt;' option, such as 'extractive|highlight-true'. Defaults to 'None'.
     *
     * @return the captions value.
     */
    public String getCaptions() {
        return this.captions;
    }

    /**
     * Set the captions property: This parameter is only valid if the query type is 'semantic'. If set, the query
     * returns captions extracted from key passages in the highest ranked documents. When Captions is set to
     * 'extractive', highlighting is enabled by default, and can be configured by appending the pipe character '|'
     * followed by the 'highlight-&lt;true/false&gt;' option, such as 'extractive|highlight-true'. Defaults to 'None'.
     *
     * @param captions the captions value to set.
     * @return the SearchRequest object itself.
     */
    public SearchRequest setCaptions(String captions) {
        this.captions = captions;
        return this;
    }

    /**
     * Get the semanticFields property: The comma-separated list of field names used for semantic search.
     *
     * @return the semanticFields value.
     */
    public String getSemanticFields() {
        return this.semanticFields;
    }

    /**
     * Set the semanticFields property: The comma-separated list of field names used for semantic search.
     *
     * @param semanticFields the semanticFields value to set.
     * @return the SearchRequest object itself.
     */
    public SearchRequest setSemanticFields(String semanticFields) {
        this.semanticFields = semanticFields;
        return this;
    }

    /**
     * Get the vector property: The query parameters for vector and hybrid search queries.
     *
     * @return the vector value.
     */
    public SearchQueryVector getVector() {
        return this.vector;
    }

    /**
     * Set the vector property: The query parameters for vector and hybrid search queries.
     *
     * @param vector the vector value to set.
     * @return the SearchRequest object itself.
     */
    public SearchRequest setVector(SearchQueryVector vector) {
        this.vector = vector;
        return this;
    }

    @Override
    public JsonWriter toJson(JsonWriter jsonWriter) throws IOException {
        jsonWriter.writeStartObject();
        jsonWriter.writeBooleanField("count", this.includeTotalResultCount);
        jsonWriter.writeArrayField("facets", this.facets, (writer, element) -> writer.writeString(element));
        jsonWriter.writeStringField("filter", this.filter);
        jsonWriter.writeStringField("highlight", this.highlightFields);
        jsonWriter.writeStringField("highlightPostTag", this.highlightPostTag);
        jsonWriter.writeStringField("highlightPreTag", this.highlightPreTag);
        jsonWriter.writeNumberField("minimumCoverage", this.minimumCoverage);
        jsonWriter.writeStringField("orderby", this.orderBy);
        jsonWriter.writeStringField("queryType", Objects.toString(this.queryType, null));
        jsonWriter.writeStringField("scoringStatistics", Objects.toString(this.scoringStatistics, null));
        jsonWriter.writeStringField("sessionId", this.sessionId);
        jsonWriter.writeArrayField(
                "scoringParameters", this.scoringParameters, (writer, element) -> writer.writeString(element));
        jsonWriter.writeStringField("scoringProfile", this.scoringProfile);
        jsonWriter.writeStringField("semanticConfiguration", this.semanticConfiguration);
        jsonWriter.writeStringField("semanticErrorHandling", Objects.toString(this.semanticErrorHandling, null));
        jsonWriter.writeNumberField("semanticMaxWaitInMilliseconds", this.semanticMaxWaitInMilliseconds);
        jsonWriter.writeStringField("debug", Objects.toString(this.debug, null));
        jsonWriter.writeStringField("search", this.searchText);
        jsonWriter.writeStringField("searchFields", this.searchFields);
        jsonWriter.writeStringField("searchMode", Objects.toString(this.searchMode, null));
        jsonWriter.writeStringField("queryLanguage", Objects.toString(this.queryLanguage, null));
        jsonWriter.writeStringField("speller", Objects.toString(this.speller, null));
        jsonWriter.writeStringField("answers", this.answers);
        jsonWriter.writeStringField("select", this.select);
        jsonWriter.writeNumberField("skip", this.skip);
        jsonWriter.writeNumberField("top", this.top);
        jsonWriter.writeStringField("captions", this.captions);
        jsonWriter.writeStringField("semanticFields", this.semanticFields);
        jsonWriter.writeJsonField("vector", this.vector);
        return jsonWriter.writeEndObject();
    }

    /**
     * Reads an instance of SearchRequest from the JsonReader.
     *
     * @param jsonReader The JsonReader being read.
     * @return An instance of SearchRequest if the JsonReader was pointing to an instance of it, or null if it was
     *     pointing to JSON null.
     * @throws IOException If an error occurs while reading the SearchRequest.
     */
    public static SearchRequest fromJson(JsonReader jsonReader) throws IOException {
        return jsonReader.readObject(
                reader -> {
                    SearchRequest deserializedSearchRequest = new SearchRequest();
                    while (reader.nextToken() != JsonToken.END_OBJECT) {
                        String fieldName = reader.getFieldName();
                        reader.nextToken();

                        if ("count".equals(fieldName)) {
                            deserializedSearchRequest.includeTotalResultCount =
                                    reader.getNullable(JsonReader::getBoolean);
                        } else if ("facets".equals(fieldName)) {
                            List<String> facets = reader.readArray(reader1 -> reader1.getString());
                            deserializedSearchRequest.facets = facets;
                        } else if ("filter".equals(fieldName)) {
                            deserializedSearchRequest.filter = reader.getString();
                        } else if ("highlight".equals(fieldName)) {
                            deserializedSearchRequest.highlightFields = reader.getString();
                        } else if ("highlightPostTag".equals(fieldName)) {
                            deserializedSearchRequest.highlightPostTag = reader.getString();
                        } else if ("highlightPreTag".equals(fieldName)) {
                            deserializedSearchRequest.highlightPreTag = reader.getString();
                        } else if ("minimumCoverage".equals(fieldName)) {
                            deserializedSearchRequest.minimumCoverage = reader.getNullable(JsonReader::getDouble);
                        } else if ("orderby".equals(fieldName)) {
                            deserializedSearchRequest.orderBy = reader.getString();
                        } else if ("queryType".equals(fieldName)) {
                            deserializedSearchRequest.queryType = QueryType.fromString(reader.getString());
                        } else if ("scoringStatistics".equals(fieldName)) {
                            deserializedSearchRequest.scoringStatistics =
                                    ScoringStatistics.fromString(reader.getString());
                        } else if ("sessionId".equals(fieldName)) {
                            deserializedSearchRequest.sessionId = reader.getString();
                        } else if ("scoringParameters".equals(fieldName)) {
                            List<String> scoringParameters = reader.readArray(reader1 -> reader1.getString());
                            deserializedSearchRequest.scoringParameters = scoringParameters;
                        } else if ("scoringProfile".equals(fieldName)) {
                            deserializedSearchRequest.scoringProfile = reader.getString();
                        } else if ("semanticConfiguration".equals(fieldName)) {
                            deserializedSearchRequest.semanticConfiguration = reader.getString();
                        } else if ("semanticErrorHandling".equals(fieldName)) {
                            deserializedSearchRequest.semanticErrorHandling =
                                    SemanticErrorHandling.fromString(reader.getString());
                        } else if ("semanticMaxWaitInMilliseconds".equals(fieldName)) {
                            deserializedSearchRequest.semanticMaxWaitInMilliseconds =
                                    reader.getNullable(JsonReader::getInt);
                        } else if ("debug".equals(fieldName)) {
                            deserializedSearchRequest.debug = QueryDebugMode.fromString(reader.getString());
                        } else if ("search".equals(fieldName)) {
                            deserializedSearchRequest.searchText = reader.getString();
                        } else if ("searchFields".equals(fieldName)) {
                            deserializedSearchRequest.searchFields = reader.getString();
                        } else if ("searchMode".equals(fieldName)) {
                            deserializedSearchRequest.searchMode = SearchMode.fromString(reader.getString());
                        } else if ("queryLanguage".equals(fieldName)) {
                            deserializedSearchRequest.queryLanguage = QueryLanguage.fromString(reader.getString());
                        } else if ("speller".equals(fieldName)) {
                            deserializedSearchRequest.speller = QuerySpellerType.fromString(reader.getString());
                        } else if ("answers".equals(fieldName)) {
                            deserializedSearchRequest.answers = reader.getString();
                        } else if ("select".equals(fieldName)) {
                            deserializedSearchRequest.select = reader.getString();
                        } else if ("skip".equals(fieldName)) {
                            deserializedSearchRequest.skip = reader.getNullable(JsonReader::getInt);
                        } else if ("top".equals(fieldName)) {
                            deserializedSearchRequest.top = reader.getNullable(JsonReader::getInt);
                        } else if ("captions".equals(fieldName)) {
                            deserializedSearchRequest.captions = reader.getString();
                        } else if ("semanticFields".equals(fieldName)) {
                            deserializedSearchRequest.semanticFields = reader.getString();
                        } else if ("vector".equals(fieldName)) {
                            deserializedSearchRequest.vector = SearchQueryVector.fromJson(reader);
                        } else {
                            reader.skipChildren();
                        }
                    }

                    return deserializedSearchRequest;
                });
    }
}
