// Copyright 2026 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

syntax = "proto3";

package google.cloud.vectorsearch.v1beta;

import "google/api/annotations.proto";
import "google/api/client.proto";
import "google/api/field_behavior.proto";
import "google/api/resource.proto";
import "google/cloud/vectorsearch/v1beta/common.proto";
import "google/cloud/vectorsearch/v1beta/data_object.proto";
import "google/cloud/vectorsearch/v1beta/embedding_config.proto";
import "google/protobuf/struct.proto";
import "google/rpc/status.proto";

option csharp_namespace = "Google.Cloud.VectorSearch.V1Beta";
option go_package = "cloud.google.com/go/vectorsearch/apiv1beta/vectorsearchpb;vectorsearchpb";
option java_multiple_files = true;
option java_outer_classname = "DataObjectSearchServiceProto";
option java_package = "com.google.cloud.vectorsearch.v1beta";
option php_namespace = "Google\\Cloud\\VectorSearch\\V1beta";
option ruby_package = "Google::Cloud::VectorSearch::V1beta";

// Service for searching data objects.
service DataObjectSearchService {
  option (google.api.default_host) = "vectorsearch.googleapis.com";
  option (google.api.oauth_scopes) =
      "https://www.googleapis.com/auth/cloud-platform";

  // Searches data objects.
  rpc SearchDataObjects(SearchDataObjectsRequest)
      returns (SearchDataObjectsResponse) {
    option (google.api.http) = {
      post: "/v1beta/{parent=projects/*/locations/*/collections/*}/dataObjects:search"
      body: "*"
    };
  }

  // Queries data objects.
  rpc QueryDataObjects(QueryDataObjectsRequest)
      returns (QueryDataObjectsResponse) {
    option (google.api.http) = {
      post: "/v1beta/{parent=projects/*/locations/*/collections/*}/dataObjects:query"
      body: "*"
    };
  }

  // Aggregates data objects.
  rpc AggregateDataObjects(AggregateDataObjectsRequest)
      returns (AggregateDataObjectsResponse) {
    option (google.api.http) = {
      post: "/v1beta/{parent=projects/*/locations/*/collections/*}/dataObjects:aggregate"
      body: "*"
    };
  }

  // Batch searches data objects.
  rpc BatchSearchDataObjects(BatchSearchDataObjectsRequest)
      returns (BatchSearchDataObjectsResponse) {
    option (google.api.http) = {
      post: "/v1beta/{parent=projects/*/locations/*/collections/*}/dataObjects:batchSearch"
      body: "*"
    };
  }
}

// Aggregation methods.
enum AggregationMethod {
  // Should not be used.
  AGGREGATION_METHOD_UNSPECIFIED = 0;

  // Count the number of data objects that match the filter.
  COUNT = 1;
}

// Defines a output fields struct for data in DataObject.
message OutputFields {
  // Optional. The fields from the data fields to include in the output.
  repeated string data_fields = 1 [(google.api.field_behavior) = OPTIONAL];

  // Optional. The fields from the vector fields to include in the output.
  repeated string vector_fields = 2 [(google.api.field_behavior) = OPTIONAL];

  // Optional. The fields from the DataObject metadata to include in the output.
  repeated string metadata_fields = 3 [(google.api.field_behavior) = OPTIONAL];
}

// Represents a hint to the search index engine.
message SearchHint {
  // Message to specify the index to use for the search.
  message IndexHint {
    // Parameters for dense ScaNN.
    message DenseScannParams {
      // Optional. Dense ANN param overrides to control recall and latency.
      // The percentage of leaves to search, in the range [0, 100].
      int32 search_leaves_pct = 1 [(google.api.field_behavior) = OPTIONAL];

      // Optional. The number of initial candidates. Must be a positive integer
      // (> 0).
      int32 initial_candidate_count = 2
          [(google.api.field_behavior) = OPTIONAL];
    }

    // The parameters for the index.
    oneof params {
      // Optional. Dense ScaNN parameters.
      DenseScannParams dense_scann_params = 2
          [(google.api.field_behavior) = OPTIONAL];
    }

    // Required. The resource name of the index to use for the search.
    // The index must be in the same project, location, and collection.
    // Format:
    // `projects/{project}/locations/{location}/collections/{collection}/indexes/{index}`
    string name = 1 [
      (google.api.field_behavior) = REQUIRED,
      (google.api.resource_reference) = {
        type: "vectorsearch.googleapis.com/Index"
      }
    ];
  }

  // KnnHint will be used if search should be explicitly done on system's
  // default K-Nearest Neighbor (KNN) index engine.
  message KnnHint {}

  // The type of index to use.
  oneof index_type {
    // Optional. Deprecated: Use `index_hint` instead.
    // Specifies that the search should use a particular index.
    IndexHint use_index = 1
        [deprecated = true, (google.api.field_behavior) = OPTIONAL];

    // Optional. Deprecated: Use `knn_hint` instead.
    // If set to true, the search will use the system's default
    // K-Nearest Neighbor (KNN) index engine.
    bool use_knn = 2
        [deprecated = true, (google.api.field_behavior) = OPTIONAL];

    // Optional. If set, the search will use the system's default
    // K-Nearest Neighbor (KNN) index engine.
    KnnHint knn_hint = 3 [(google.api.field_behavior) = OPTIONAL];

    // Optional. Specifies that the search should use a particular index.
    IndexHint index_hint = 4 [(google.api.field_behavior) = OPTIONAL];
  }
}

// A single search request within a batch operation.
message Search {
  // The type of search to perform.
  oneof search_type {
    // A vector-based search.
    VectorSearch vector_search = 1;

    // A semantic search.
    SemanticSearch semantic_search = 2;

    // A text search operation.
    TextSearch text_search = 3;
  }
}

// Defines a search operation using a query vector.
message VectorSearch {
  // Specifies the type of vector to use for the query.
  oneof vector_type {
    // A dense vector for the query.
    DenseVector vector = 1;

    // A sparse vector for the query.
    SparseVector sparse_vector = 2;
  }

  // Required. The vector field to search.
  string search_field = 8 [(google.api.field_behavior) = REQUIRED];

  // Optional. A JSON filter expression, e.g. {"genre": {"$eq": "sci-fi"}},
  // represented as a google.protobuf.Struct.
  google.protobuf.Struct filter = 4 [(google.api.field_behavior) = OPTIONAL];

  // Optional. The number of nearest neighbors to return.
  optional int32 top_k = 5 [(google.api.field_behavior) = OPTIONAL];

  // Optional. Mask specifying which fields to return.
  OutputFields output_fields = 7 [(google.api.field_behavior) = OPTIONAL];

  // Optional. Sets the search hint. If no strategy is specified, the service
  // will use an index if one is available, and fall back to the default KNN
  // search otherwise.
  SearchHint search_hint = 9 [(google.api.field_behavior) = OPTIONAL];

  // Optional. The distance metric to use for the KNN search. If not specified,
  // DOT_PRODUCT will be used as the default.
  DistanceMetric distance_metric = 11 [(google.api.field_behavior) = OPTIONAL];
}

// Defines a semantic search operation.
message SemanticSearch {
  // Required. The query text, which is used to generate an embedding according
  // to the embedding model specified in the collection config.
  string search_text = 1 [(google.api.field_behavior) = REQUIRED];

  // Required. The vector field to search.
  string search_field = 2 [(google.api.field_behavior) = REQUIRED];

  // Required. The task type of the query embedding.
  EmbeddingTaskType task_type = 5 [(google.api.field_behavior) = REQUIRED];

  // Optional. The fields to return in the search results.
  OutputFields output_fields = 3 [(google.api.field_behavior) = OPTIONAL];

  // Optional. A JSON filter expression, e.g. {"genre": {"$eq": "sci-fi"}},
  // represented as a google.protobuf.Struct.
  google.protobuf.Struct filter = 6 [(google.api.field_behavior) = OPTIONAL];

  // Optional. The number of data objects to return.
  optional int32 top_k = 4 [(google.api.field_behavior) = OPTIONAL];

  // Optional. Sets the search hint. If no strategy is specified, the service
  // will use an index if one is available, and fall back to KNN search
  // otherwise.
  SearchHint search_hint = 7 [(google.api.field_behavior) = OPTIONAL];
}

// Defines a text search operation.
message TextSearch {
  // Required. The query text.
  string search_text = 1 [(google.api.field_behavior) = REQUIRED];

  // Required. The data field names to search.
  repeated string data_field_names = 2 [(google.api.field_behavior) = REQUIRED];

  // Optional. The fields to return in the search results.
  OutputFields output_fields = 3 [(google.api.field_behavior) = OPTIONAL];

  // Optional. The number of results to return.
  optional int32 top_k = 4 [(google.api.field_behavior) = OPTIONAL];

  // Optional. A JSON filter expression, e.g. `{"genre": {"$eq": "sci-fi"}}`,
  // represented as a `google.protobuf.Struct`.
  google.protobuf.Struct filter = 5 [(google.api.field_behavior) = OPTIONAL];
}

// Request for performing a single search.
message SearchDataObjectsRequest {
  // The query to search for.
  oneof search_type {
    // A vector search operation.
    VectorSearch vector_search = 2;

    // A semantic search operation.
    SemanticSearch semantic_search = 4;

    // Optional. A text search operation.
    TextSearch text_search = 7 [(google.api.field_behavior) = OPTIONAL];
  }

  // Required. The resource name of the Collection for which to search.
  // Format: `projects/{project}/locations/{location}/collections/{collection}`
  string parent = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "vectorsearch.googleapis.com/Collection"
    }
  ];

  // Optional. The standard list page size. Only supported for KNN. If not set,
  // up to search_type.top_k results will be returned. The maximum value is
  // 1000; values above 1000 will be coerced to 1000.
  int32 page_size = 5 [(google.api.field_behavior) = OPTIONAL];

  // Optional. The standard list page token.
  // Typically obtained via
  // [SearchDataObjectsResponse.next_page_token][google.cloud.vectorsearch.v1beta.SearchDataObjectsResponse.next_page_token]
  // of the previous
  // [DataObjectSearchService.SearchDataObjects][google.cloud.vectorsearch.v1beta.DataObjectSearchService.SearchDataObjects]
  // call.
  string page_token = 6 [(google.api.field_behavior) = OPTIONAL];
}

// A single search result.
message SearchResult {
  // Output only. The matching data object.
  DataObject data_object = 1 [(google.api.field_behavior) = OUTPUT_ONLY];

  // Output only. Similarity distance or ranker score returned by
  // BatchSearchDataObjects.
  optional double distance = 2 [(google.api.field_behavior) = OUTPUT_ONLY];
}

// Metadata about the search execution.
message SearchResponseMetadata {
  // Message that indicates the index used for the search.
  message IndexInfo {
    // Output only. The resource name of the index used for the search.
    // Format:
    // `projects/{project}/locations/{location}/collections/{collection}/indexes/{index}`
    string name = 1 [
      (google.api.field_behavior) = OUTPUT_ONLY,
      (google.api.resource_reference) = {
        type: "vectorsearch.googleapis.com/Index"
      }
    ];
  }

  // The type of index used.
  oneof index_type {
    // Indicates that the search used a particular index.
    IndexInfo used_index = 1;

    // Output only. If true, the search used the system's default
    // K-Nearest Neighbor (KNN) index engine.
    bool used_knn = 2 [(google.api.field_behavior) = OUTPUT_ONLY];
  }

  // Output only. Warnings or non-fatal errors that occurred during execution.
  repeated google.rpc.Status warnings = 3
      [(google.api.field_behavior) = OUTPUT_ONLY];
}

// Response for a search request.
message SearchDataObjectsResponse {
  // Output only. The list of dataObjects that match the search criteria.
  repeated SearchResult results = 1 [(google.api.field_behavior) = OUTPUT_ONLY];

  // Output only. A token to retrieve next page of results.
  // Pass to [DataObjectSearchService.SearchDataObjectsRequest.page_token][] to
  // obtain that page.
  string next_page_token = 2 [(google.api.field_behavior) = OUTPUT_ONLY];

  // Output only. Metadata about the search execution.
  SearchResponseMetadata search_response_metadata = 3
      [(google.api.field_behavior) = OUTPUT_ONLY];
}

// Request message for
// [DataObjectSearchService.AggregateDataObjects][google.cloud.vectorsearch.v1beta.DataObjectSearchService.AggregateDataObjects].
message AggregateDataObjectsRequest {
  // Required. The resource name of the Collection for which to query.
  // Format: `projects/{project}/locations/{location}/collections/{collection}`
  string parent = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "vectorsearch.googleapis.com/Collection"
    }
  ];

  // Optional. A JSON filter expression, e.g. {"genre": {"$eq": "sci-fi"}},
  // represented as a google.protobuf.Struct.
  google.protobuf.Struct filter = 2 [(google.api.field_behavior) = OPTIONAL];

  // Required. The aggregation method to apply to the query.
  AggregationMethod aggregate = 3 [(google.api.field_behavior) = REQUIRED];
}

// Response message for
// [DataObjectSearchService.AggregateDataObjects][google.cloud.vectorsearch.v1beta.DataObjectSearchService.AggregateDataObjects].
message AggregateDataObjectsResponse {
  // Output only. The aggregated results of the query.
  repeated google.protobuf.Struct aggregate_results = 1
      [(google.api.field_behavior) = OUTPUT_ONLY];
}

// Request message for
// [DataObjectSearchService.QueryDataObjects][google.cloud.vectorsearch.v1beta.DataObjectSearchService.QueryDataObjects].
message QueryDataObjectsRequest {
  // Required. The resource name of the Collection for which to query.
  // Format: `projects/{project}/locations/{location}/collections/{collection}`
  string parent = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "vectorsearch.googleapis.com/Collection"
    }
  ];

  // Optional. A JSON filter expression, e.g. {"genre": {"$eq": "sci-fi"}},
  // represented as a google.protobuf.Struct.
  google.protobuf.Struct filter = 2 [(google.api.field_behavior) = OPTIONAL];

  // Optional. Mask specifying which fields to return.
  OutputFields output_fields = 7 [(google.api.field_behavior) = OPTIONAL];

  // Optional. The standard list page size. Default is 100.
  // The maximum value is 1000; values above 1000 will be coerced to 1000.
  int32 page_size = 5 [(google.api.field_behavior) = OPTIONAL];

  // Optional. The standard list page token.
  // Typically obtained via
  // [QueryDataObjectsResponse.next_page_token][google.cloud.vectorsearch.v1beta.QueryDataObjectsResponse.next_page_token]
  // of the previous
  // [DataObjectSearchService.QueryDataObjects][google.cloud.vectorsearch.v1beta.DataObjectSearchService.QueryDataObjects]
  // call.
  string page_token = 6 [(google.api.field_behavior) = OPTIONAL];
}

// Response message for
// [DataObjectSearchService.QueryDataObjects][google.cloud.vectorsearch.v1beta.DataObjectSearchService.QueryDataObjects].
message QueryDataObjectsResponse {
  // Output only. The list of dataObjects that match the query.
  repeated DataObject data_objects = 4
      [(google.api.field_behavior) = OUTPUT_ONLY];

  // Output only. A token to retrieve next page of results.
  // Pass to [DataObjectSearchService.QueryDataObjectsRequest.page_token][] to
  // obtain that page.
  string next_page_token = 3 [(google.api.field_behavior) = OUTPUT_ONLY];
}

// A request to perform a batch of search operations.
message BatchSearchDataObjectsRequest {
  // Options for combining the results of the batch search operations.
  message CombineResultsOptions {
    // Required. The ranker to use for combining the results.
    Ranker ranker = 1 [(google.api.field_behavior) = REQUIRED];

    // Optional. Mask specifying which fields to return.
    OutputFields output_fields = 2 [(google.api.field_behavior) = OPTIONAL];

    // Optional. The number of results to return. If not set, a default value
    // will be used.
    int32 top_k = 3 [(google.api.field_behavior) = OPTIONAL];
  }

  // Required. The resource name of the Collection for which to search.
  // Format: `projects/{project}/locations/{location}/collections/{collection}`
  string parent = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "vectorsearch.googleapis.com/Collection"
    }
  ];

  // Required. A list of search requests to execute in parallel.
  repeated Search searches = 2 [(google.api.field_behavior) = REQUIRED];

  // Optional. Options for combining the results of the batch search operations.
  CombineResultsOptions combine = 3 [(google.api.field_behavior) = OPTIONAL];
}

// Defines a ranker to combine results from multiple searches.
message Ranker {
  // The ranking method to use.
  oneof ranker {
    // Reciprocal Rank Fusion ranking.
    ReciprocalRankFusion rrf = 1;
  }

  // The reranker to use for final ranking of the results combined by the
  // ranker.
  oneof reranker {
    // Optional. Vertex AI ranking.
    VertexRanker vertex_ranker = 2 [(google.api.field_behavior) = OPTIONAL];
  }
}

// Defines the Reciprocal Rank Fusion (RRF) algorithm for result ranking.
message ReciprocalRankFusion {
  // Required. The weights to apply to each search result set during fusion.
  repeated double weights = 1 [(google.api.field_behavior) = REQUIRED];
}

// Defines a ranker using the Vertex AI ranking service.
// See https://cloud.google.com/generative-ai-app-builder/docs/ranking for
// details.
message VertexRanker {
  // The record spec for text search.
  message TextRecordSpec {
    // Required. The query against which the records are ranked and scored.
    string query = 1 [(google.api.field_behavior) = REQUIRED];

    // Optional. The template used to generate the record's title.
    string title_template = 2 [(google.api.field_behavior) = OPTIONAL];

    // Optional. The template used to generate the record's content.
    string content_template = 3 [(google.api.field_behavior) = OPTIONAL];
  }

  // The record specification for ranking. At least one record spec must be
  // set.
  oneof record_spec {
    // The record spec for text search.
    TextRecordSpec text_record_spec = 6;
  }

  // Required. The model used for ranking documents. The list of available
  // models is described in
  // https://docs.cloud.google.com/generative-ai-app-builder/docs/ranking#models.
  // Currently, only `semantic-ranker-fast@latest` is supported.
  string model = 4 [(google.api.field_behavior) = REQUIRED];

  // Required. The number of documents to be processed for ranking.
  int32 top_n = 5 [(google.api.field_behavior) = REQUIRED];
}

// A response from a batch search operation.
message BatchSearchDataObjectsResponse {
  // Output only. A list of search responses, one for each request in the batch.
  // If a ranker is used, a single ranked list of results is returned.
  repeated SearchDataObjectsResponse results = 1
      [(google.api.field_behavior) = OUTPUT_ONLY];
}
