syntax = "proto3";

import "status.proto";

package milvus.grpc;

/**
 * @brief general usage
 */
message KeyValuePair {
    string key = 1;
    string value = 2;
}

/**
 * @brief Collection name
 */
message CollectionName {
    string collection_name = 1;
}

/**
 * @brief Collection name list
 */
message CollectionNameList {
    Status status = 1;
    repeated string collection_names = 2;
}

/**
 * @brief Collection schema
 * metric_type: 1-L2, 2-IP
 */
message CollectionSchema {
    Status status = 1;
    string collection_name = 2;
    int64 dimension = 3;
    int64 index_file_size = 4;
    int32 metric_type = 5;
    repeated KeyValuePair extra_params = 6;
}

/**
 * @brief Params of partition
 */
message PartitionParam {
    string collection_name = 1;
    string tag = 2;
}

/**
 * @brief Partition list
 */
message PartitionList {
    Status status = 1;
    repeated string partition_tag_array = 2;
}

/**
 * @brief Record inserted
 */
message RowRecord {
    repeated float float_data = 1;             //float vector data
    bytes binary_data = 2;                      //binary vector data
}

/**
 * @brief Params to be inserted
 */
message InsertParam {
    string collection_name = 1;
    repeated RowRecord row_record_array = 2;
    repeated int64 row_id_array = 3;            //optional
    string partition_tag = 4;
    repeated KeyValuePair extra_params = 5;
}

/**
 * @brief Vector ids
 */
message VectorIds {
    Status status = 1;
    repeated int64 vector_id_array = 2;
}

/**
 * @brief Params for searching vector
 */
message SearchParam {
    string collection_name = 1;
    repeated string partition_tag_array = 2;
    repeated RowRecord query_record_array = 3;
    int64 topk = 4;
    repeated KeyValuePair extra_params = 5;
}

/**
 * @brief Params for searching vector in files
 */
message SearchInFilesParam {
    repeated string file_id_array = 1;
    SearchParam search_param = 2;
}

/**
 * @brief Params for searching vector by ID
 */
message SearchByIDParam {
    string collection_name = 1;
    repeated string partition_tag_array = 2;
    repeated int64 id_array = 3;
    int64 topk = 4;
    repeated KeyValuePair extra_params = 5;
}

/**
 * @brief Query result params
 */
message TopKQueryResult {
    Status status = 1;
    int64 row_num = 2;
    repeated int64 ids = 3;
    repeated float distances = 4;
}

/**
 * @brief Server string Reply
 */
message StringReply {
    Status status = 1;
    string string_reply = 2;
}

/**
 * @brief Server bool Reply
 */
message BoolReply {
    Status status = 1;
    bool bool_reply = 2;
}

/**
 * @brief Return collection row count
 */
message CollectionRowCount {
    Status status = 1;
    int64 collection_row_count = 2;
}

/**
 * @brief Give server Command
 */
message Command {
    string cmd = 1;
}

/**
 * @brief Index params
 * @index_type: 0-invalid, 1-idmap, 2-ivflat, 3-ivfsq8, 4-nsgmix
 */
message IndexParam {
    Status status = 1;
    string collection_name = 2;
    int32 index_type = 3;
    repeated KeyValuePair extra_params = 4;
}

/**
 * @brief Flush params
 */
message FlushParam {
    repeated string collection_name_array = 1;
}

/**
 * @brief Flush params
 */
message DeleteByIDParam {
    string collection_name = 1;
    repeated int64 id_array = 2;
}

/**
 * @brief collection information
 */
message CollectionInfo {
    Status status = 1;
    string json_info = 2;
}

/**
 * @brief vectors identity
 */
message VectorsIdentity {
    string collection_name = 1;
    repeated int64 id_array = 2;
}

/**
 * @brief vector data
 */
message VectorsData {
    Status status = 1;
    repeated RowRecord vectors_data = 2;
}

/**
 * @brief get vector ids from a segment parameters
 */
message GetVectorIDsParam {
    string collection_name = 1;
    string segment_name = 2;
}


/********************************************************************************************************************/

enum DataType {
    NULL = 0;
    INT8 = 1;
    INT16 = 2;
    INT32 = 3;
    INT64 = 4;

    STRING = 20;

    BOOL = 30;

    FLOAT = 40;
    DOUBLE = 41;

    VECTOR = 100;
    UNKNOWN = 9999;
}

///////////////////////////////////////////////////////////////////

message VectorFieldParam {
    int64 dimension = 1;
}

message FieldType {
    oneof value {
        DataType data_type = 1;
        VectorFieldParam vector_param = 2;
    }
}

message FieldParam {
    uint64 id = 1;
    string name = 2;
    FieldType type = 3;
    repeated KeyValuePair extra_params = 4;
}

message VectorFieldValue {
    repeated RowRecord value = 1;
}

message FieldValue {
    oneof value {
        int32 int32_value = 1;
        int64 int64_value = 2;
        float float_value = 3;
        double double_value = 4;
        string string_value = 5;
        bool  bool_value = 6;
        VectorFieldValue vector_value = 7;
    }
}

///////////////////////////////////////////////////////////////////

message Mapping {
    Status status = 1;
    uint64 collection_id = 2;
    string collection_name = 3;
    repeated FieldParam fields = 4;
}

message MappingList {
    Status status = 1;
    repeated Mapping mapping_list = 2;
}

///////////////////////////////////////////////////////////////////

message TermQuery {
    string field_name = 1;
    bytes values = 2;
    int64 value_num = 3;
    float boost = 4;
    repeated KeyValuePair extra_params = 5;
}

enum CompareOperator {
    LT = 0;
    LTE = 1;
    EQ = 2;
    GT = 3;
    GTE = 4;
    NE = 5;
}

message CompareExpr {
    CompareOperator operator = 1;
    string operand = 2;
}

message RangeQuery {
    string field_name = 1;
    repeated CompareExpr operand = 2;
    float boost = 3;
    repeated KeyValuePair extra_params = 4;
}

message VectorQuery {
    string field_name = 1;
    float query_boost = 2;
    repeated RowRecord records = 3;
    int64 topk = 4;
    repeated KeyValuePair extra_params = 5;
}

enum Occur {
    INVALID = 0;
    MUST = 1;
    SHOULD = 2;
    MUST_NOT = 3;
}

message BooleanQuery {
    Occur occur = 1;
    repeated GeneralQuery general_query = 2;
}

message GeneralQuery {
    oneof query {
        BooleanQuery boolean_query = 1;
        TermQuery term_query = 2;
        RangeQuery range_query = 3;
        VectorQuery vector_query = 4;
    }
}

message HSearchParam {
    string collection_name = 1;
    repeated string partition_tag_array = 2;
    GeneralQuery general_query = 3;
    repeated KeyValuePair extra_params = 4;
}

message HSearchInSegmentsParam {
    repeated string segment_id_array = 1;
    HSearchParam search_param = 2;
}

///////////////////////////////////////////////////////////////////

message AttrRecord {
    repeated string value = 1;
}

message HEntity {
    Status status = 1;
    int64 entity_id = 2;
    repeated string field_names = 3;
    bytes attr_records = 4;
    int64 row_num = 5;
    repeated FieldValue result_values = 6;
}

message HQueryResult {
    Status status = 1;
    repeated HEntity entities = 2;
    int64 row_num = 3;
    repeated float score = 4;
    repeated float distance = 5;
}

message HInsertParam {
    string collection_name = 1;
    string partition_tag = 2;
    HEntity entities = 3;
    repeated int64 entity_id_array = 4;
    repeated KeyValuePair extra_params = 5;
}

message HEntityIdentity {
    string collection_name = 1;
    int64 id = 2;
}

message HEntityIDs {
    Status status = 1;
    repeated int64 entity_id_array = 2;
}

message HGetEntityIDsParam {
    string collection_name = 1;
    string segment_name = 2;
}

message HDeleteByIDParam {
    string collection_name = 1;
    repeated int64 id_array = 2;
}

///////////////////////////////////////////////////////////////////

message HIndexParam {
    Status status = 1;
    string collection_name = 2;
    int32 index_type = 3;
    repeated KeyValuePair extra_params = 4;
}


service MilvusService {
    /**
     * @brief This method is used to create collection
     *
     * @param CollectionSchema, use to provide collection information to be created.
     *
     * @return Status
     */
    rpc CreateCollection(CollectionSchema) returns (Status){}

    /**
     * @brief This method is used to test collection existence.
     *
     * @param CollectionName, collection name is going to be tested.
     *
     * @return BoolReply
     */
    rpc HasCollection(CollectionName) returns (BoolReply) {}

    /**
     * @brief This method is used to get collection schema.
     *
     * @param CollectionName, target collection name.
     *
     * @return CollectionSchema
     */
    rpc DescribeCollection(CollectionName) returns (CollectionSchema) {}

    /**
     * @brief This method is used to get collection schema.
     *
     * @param CollectionName, target collection name.
     *
     * @return CollectionRowCount
     */
    rpc CountCollection(CollectionName) returns (CollectionRowCount) {}

    /**
     * @brief This method is used to list all collections.
     *
     * @param Command, dummy parameter.
     *
     * @return CollectionNameList
     */
    rpc ShowCollections(Command) returns (CollectionNameList) {}

    /**
     * @brief This method is used to get collection detail information.
     *
     * @param CollectionName, target collection name.
     *
     * @return CollectionInfo
     */
    rpc ShowCollectionInfo(CollectionName) returns (CollectionInfo) {}

    /**
     * @brief This method is used to delete collection.
     *
     * @param CollectionName, collection name is going to be deleted.
     *
     * @return CollectionNameList
     */
    rpc DropCollection(CollectionName) returns (Status) {}

    /**
     * @brief This method is used to build index by collection in sync mode.
     *
     * @param IndexParam, index paramters.
     *
     * @return Status
     */
    rpc CreateIndex(IndexParam) returns (Status) {}

    /**
     * @brief This method is used to describe index
     *
     * @param CollectionName, target collection name.
     *
     * @return IndexParam
     */
    rpc DescribeIndex(CollectionName) returns (IndexParam) {}

    /**
     * @brief This method is used to drop index
     *
     * @param CollectionName, target collection name.
     *
     * @return Status
     */
    rpc DropIndex(CollectionName) returns (Status) {}

    /**
     * @brief This method is used to create partition
     *
     * @param PartitionParam, partition parameters.
     *
     * @return Status
     */
    rpc CreatePartition(PartitionParam) returns (Status) {}

    /**
     * @brief This method is used to test partition existence.
     *
     * @param PartitionParam, target partition.
     *
     * @return BoolReply
     */
    rpc HasPartition(PartitionParam) returns (BoolReply) {}

    /**
     * @brief This method is used to show partition information
     *
     * @param CollectionName, target collection name.
     *
     * @return PartitionList
     */
    rpc ShowPartitions(CollectionName) returns (PartitionList) {}

    /**
     * @brief This method is used to drop partition
     *
     * @param PartitionParam, target partition.
     *
     * @return Status
     */
    rpc DropPartition(PartitionParam) returns (Status) {}

    /**
     * @brief This method is used to add vector array to collection.
     *
     * @param InsertParam, insert parameters.
     *
     * @return VectorIds
     */
    rpc Insert(InsertParam) returns (VectorIds) {}

    /**
     * @brief This method is used to get vectors data by id array.
     *
     * @param VectorsIdentity, target vector id array.
     *
     * @return VectorsData
     */
    rpc GetVectorsByID(VectorsIdentity) returns (VectorsData) {}

    /**
     * @brief This method is used to get vector ids from a segment
     *
     * @param GetVectorIDsParam, target collection and segment
     *
     * @return VectorIds
     */
    rpc GetVectorIDs(GetVectorIDsParam) returns (VectorIds) {}

    /**
     * @brief This method is used to query vector in collection.
     *
     * @param SearchParam, search parameters.
     *
     * @return TopKQueryResult
     */
    rpc Search(SearchParam) returns (TopKQueryResult) {}

    /**
     * @brief This method is used to query vector by id.
     *
     * @param SearchByIDParam, search parameters.
     *
     * @return TopKQueryResult
     */
    rpc SearchByID(SearchByIDParam) returns (TopKQueryResult) {}

    /**
     * @brief This method is used to query vector in specified files.
     *
     * @param SearchInFilesParam, search in files paremeters.
     *
     * @return TopKQueryResult
     */
    rpc SearchInFiles(SearchInFilesParam) returns (TopKQueryResult) {}

    /**
     * @brief This method is used to give the server status.
     *
     * @param Command, command string
     *
     * @return StringReply
     */
    rpc Cmd(Command) returns (StringReply) {}

    /**
     * @brief This method is used to delete vector by id
     *
     * @param DeleteByIDParam, delete parameters.
     *
     * @return status
     */
    rpc DeleteByID(DeleteByIDParam) returns (Status) {}

    /**
     * @brief This method is used to preload collection
     *
     * @param CollectionName, target collection name.
     *
     * @return Status
     */
    rpc PreloadCollection(CollectionName) returns (Status) {}

    /**
     * @brief This method is used to flush buffer into storage.
     *
     * @param FlushParam, flush parameters
     *
     * @return Status
     */
    rpc Flush(FlushParam) returns (Status) {}

    /**
     * @brief This method is used to compact collection
     *
     * @param CollectionName, target collection name.
     *
     * @return Status
     */
    rpc Compact(CollectionName) returns (Status) {}

    /********************************New Interface********************************************/

    rpc CreateHybridCollection(Mapping) returns (Status) {}

    rpc HasHybridCollection(CollectionName) returns (BoolReply) {}

    rpc DropHybridCollection(CollectionName) returns (Status) {}

    rpc DescribeHybridCollection(CollectionName) returns (Mapping) {}

    rpc CountHybridCollection(CollectionName) returns (CollectionRowCount) {}

    rpc ShowHybridCollections(Command) returns (MappingList) {}

    rpc ShowHybridCollectionInfo (CollectionName) returns (CollectionInfo) {}

    rpc PreloadHybridCollection(CollectionName) returns (Status) {}

    ///////////////////////////////////////////////////////////////////

//    rpc CreateIndex(IndexParam) returns (Status) {}
//
//    rpc DescribeIndex(CollectionName) returns (IndexParam) {}
//
//    rpc DropIndex(CollectionName) returns (Status) {}

    ///////////////////////////////////////////////////////////////////

    rpc InsertEntity(HInsertParam) returns (HEntityIDs) {}

    // TODO(yukun): will change to HQueryResult
    rpc HybridSearch(HSearchParam) returns (TopKQueryResult) {}

    rpc HybridSearchInSegments(HSearchInSegmentsParam) returns (TopKQueryResult) {}

    rpc GetEntityByID(HEntityIdentity) returns (HEntity) {}

    rpc GetEntityIDs(HGetEntityIDsParam) returns (HEntityIDs) {}

    rpc DeleteEntitiesByID(HDeleteByIDParam) returns (Status) {}

    ///////////////////////////////////////////////////////////////////
}