syntax = "proto3";

import "status.proto";

package milvus.grpc;

/**
 * @brief Field data type
 */
enum DataType {
    NONE = 0;
    BOOL = 1;
    INT8 = 2;
    INT16 = 3;
    INT32 = 4;
    INT64 = 5;

    FLOAT = 10;
    DOUBLE = 11;

    STRING = 20;

    VECTOR_BINARY = 100;
    VECTOR_FLOAT = 101;
}

/**
 * @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 Field name
 */
message FieldName {
    string collection_name = 1;
    string field_name = 2;
}

/**
 * @brief Collection mapping
 * @extra_params: key-value pair for extra parameters of the collection
 *    typically usage:
 *        extra_params["params"] = {segment_row_count: 1000000, auto_id: true}
 *    Note:
 *        the segment_row_count specify segment row count limit for merging
 *        the auto_id = true means entity id is auto-generated by milvus
 */
message Mapping {
    Status status = 1;
    string collection_name = 2;
    repeated FieldParam fields = 3;
    repeated KeyValuePair extra_params = 4;
}

/**
 * @brief Collection mapping list
 */
message MappingList {
    Status status = 1;
    repeated Mapping mapping_list = 2;
}

/**
 * @brief Parameters 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 Vector row record
 */
message VectorRowRecord {
    repeated float float_data = 1;             //float vector data
    bytes binary_data = 2;                      //binary vector data
}

/**
 * @brief Attribute record
 */
message AttrRecord {
    repeated int32 int32_value = 1;
    repeated int64 int64_value = 2;
    repeated float float_value = 3;
    repeated double double_value = 4;
}

/**
 * @brief Vector records
 */
message VectorRecord {
    repeated VectorRowRecord records = 1;
}

/**
 * @brief Field values
 */
message FieldValue {
    string field_name = 1;
    DataType type = 2;
    AttrRecord attr_record = 3;
    VectorRecord vector_record = 4;
}

/**
 * @brief Parameters for insert action
 */
message InsertParam {
    string collection_name = 1;
    repeated FieldValue fields = 2;
    repeated int64 entity_id_array = 3;            //optional
    string partition_tag = 4;
    repeated KeyValuePair extra_params = 5;
}

/**
 * @brief Entity ids
 */
message EntityIds {
    Status status = 1;
    repeated int64 entity_id_array = 2;
}

/**
 * @brief Search vector parameters
 */
message VectorParam {
    string json = 1;
    VectorRecord row_record = 2;
}

/**
 * @brief Parameters for search action
 * @dsl example:
 *    {
 *   "query": {
 *       "bool": {
 *           "must": [
 *               {
 *                   "must":[
 *                       {
 *                           "should": [
 *                               {
 *                                   "term": {
 *                                       "gender": ["male"]
 *                                   }
 *                               },
 *                               {
 *                                   "range": {
 *                                       "height": {"gte": "170.0", "lte": "180.0"}
 *                                   }
 *                               }
 *                           ]
 *                       },
 *                       {
 *                           "must_not": [
 *                               {
 *                                   "term": {
 *                                       "age": [20, 21, 22, 23, 24, 25]
 *                                   }
 *                               },
 *                               {
 *                                   "Range": {
 *                                       "weight": {"lte": "100"}
 *                                   }
 *                               }
 *                           ]
 *                       }
 *                   ]
 *               },
 *               {
 *                   "must": [
 *                       {
 *                           "vector": {
 *                               "face_img": {
 *                                   "topk": 10,
 *                                   "metric_type": "L2",
 *                                   "query": [],
 *                                   "params": {
 *                                       "nprobe": 10
 *                                   }
 *                               }
 *                           }
 *                       }
 *                   ]
 *               }
 *           ]
 *       }
 *   },
 *   "fields": ["age", "face_img"]
 *   }
 */
message SearchParam {
    string collection_name = 1;
    repeated string partition_tag_array = 2;
    repeated VectorParam vector_param = 3;
    string dsl = 4;
    repeated KeyValuePair extra_params = 5;
}

/**
 * @brief Parameters for searching in segments
 */
message SearchInSegmentParam {
    repeated string file_id_array = 1;
    SearchParam search_param = 2;
}

/**
 * @brief Entities
 */
message Entities {
    Status status = 1;
    repeated int64 ids = 2;
    repeated bool valid_row = 3;
    repeated FieldValue fields = 4;
}

/**
 * @brief Query result
 */
message QueryResult {
    Status status = 1;
    Entities entities = 2;
    int64 row_num = 3;
    repeated float scores = 4;
    repeated float distances = 5;
    repeated KeyValuePair extra_params = 6;
}

/**
 * @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 Server command parameters
 */
message Command {
    string cmd = 1;
}

/**
 * @brief Index params
 * @collection_name: target collection
 * @field_name: target field
 * @index_name: a name for index provided by user, unique within this field
 * @extra_params: index parameters in json format
 *    for vector field:
 *        extra_params["index_type"] = one of the values: FLAT, IVF_LAT, IVF_SQ8, NSGMIX, IVFSQ8H,
 *                                                        PQ, HNSW, HNSW_SQ8NM, ANNOY
 *        extra_params["metric_type"] = one of the values: L2, IP, HAMMING, JACCARD, TANIMOTO
 *                                                         SUBSTRUCTURE, SUPERSTRUCTURE
 *        extra_params["params"] = extra parameters for index, for example ivflat: {nlist: 2048}
 *    for structured field:
 *        extra_params["index_type"] = one of the values: SORTED
 */
message IndexParam {
    Status status = 1;
    string collection_name = 2;
    string field_name = 3;
    string index_name = 4;
    repeated KeyValuePair extra_params = 5;
}

/**
 * @brief Parameters for flush action
 */
message FlushParam {
    repeated string collection_name_array = 1;
}

/**
 * @brief Parameters for flush action
 */
message CompactParam {
    string collection_name = 1;
    double threshold = 2;
}

/**
 * @brief Parameters for deleting entities by id
 */
message DeleteByIDParam {
    string collection_name = 1;
    repeated int64 id_array = 2;
}

/**
 * @brief Return collection stats
 * @json_info: collection stats in json format, typically, the format is like:
 *     {
 *        row_count: xxx,
 *        data_size: xxx,
 *        partitions: [
 *          {
 *            tag: xxx,
 *            id: xxx,
 *            row_count: xxx,
 *            data_size: xxx,
 *            segments: [
 *              {
 *                 id: xxx,
 *                 row_count: xxx,
 *                 data_size: xxx,
 *                 files: [
 *                    {
 *                       field: xxx,
 *                       name: xxx,
 *                       index_type: xxx,
 *                       path: xxx,
 *                       data_size: xxx,
 *                    }
 *                 ]
 *              }
 *            ]
 *          }
 *        ]
 *     }
 */
message CollectionInfo {
    Status status = 1;
    string json_info = 2;
}

/**
 * @brief Parameters for returning entities id of a segment
 */
message GetEntityIDsParam {
    string collection_name = 1;
    int64 segment_id = 2;
}

/**
 * @brief Entities identity
 */
message EntityIdentity {
    string collection_name = 1;
    repeated int64 id_array = 2;
    repeated string field_names = 3;
}

/********************************************SearchPB interface***************************************************/
/**
 * @brief Vector field parameters
 */
message VectorFieldParam {
    int64 dimension = 1;
}

/**
 * @brief Field type
 */
message FieldType {
    oneof value {
        DataType data_type = 1;
        VectorFieldParam vector_param = 2;
    }
}

/**
 * @brief Field parameters
 */
message FieldParam {
    uint64 id = 1;
    string name = 2;
    DataType type = 3;
    repeated KeyValuePair index_params = 4;
    repeated KeyValuePair extra_params = 5;
}

/**
 * @brief Vector field record
 */
message VectorFieldRecord {
    repeated VectorRowRecord value = 1;
}

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

message TermQuery {
    string field_name = 1;
    repeated int64 int_value = 2;
    repeated double double_value = 3;
    int64 value_num = 4;
    float boost = 5;
    repeated KeyValuePair extra_params = 6;
}

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 VectorRowRecord 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 SearchParamPB {
    string collection_name = 1;
    repeated string partition_tag_array = 2;
    GeneralQuery general_query = 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(Mapping) 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 (Mapping) {}

    /**
     * @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 Status
     */
    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 IndexParam, target index.
     *
     * @return IndexParam
     */
    rpc DescribeIndex(IndexParam) returns (IndexParam) {}

    /**
     * @brief This method is used to drop index
     *
     * @param IndexParam, target field. if the IndexParam.field_name is empty, will drop all index of the collection
     *
     * @return Status
     */
    rpc DropIndex(IndexParam) 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 (EntityIds) {}

    /**
     * @brief This method is used to get entities data by id array.
     *
     * @param EntitiesIdentity, target entity id array.
     *
     * @return EntitiesData
     */
    rpc GetEntityByID(EntityIdentity) returns (Entities) {}

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

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

    /**
     * @brief This method is used to query vector in specified files.
     *
     * @param SearchInSegmentParam, target segments to search.
     *
     * @return TopKQueryResult
     */
    rpc SearchInSegment(SearchInSegmentParam) returns (QueryResult) {}

    /**
     * @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 CompactParam, compact parameters
     *
     * @return Status
     */
    rpc Compact(CompactParam) returns (Status) {}

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

    rpc SearchPB(SearchParamPB) returns (QueryResult) {}
}