syntax = "proto3";

package wix.os.v1.upstream.wix.common;

import "google/protobuf/struct.proto";
import "google/protobuf/wrappers.proto";
import "wix/os/v1/upstream/wix/common/paging.proto";
import "wix/os/v1/upstream/wix/common/sorting.proto";
import "wix/api/annotations.proto";
import "wix/api/validations.proto";

option java_multiple_files = true;
option java_outer_classname = "QueryProto";
option java_package = "com.wixpress.os.v1.upstream.wix.common";

message CursorQuery {
    option (.wix.api.decomposite_of) = "wix.common.CursorQuery";
    // Filter object.
    //
    // Learn more about the [filter section](https://dev.wix.com/docs/rest/articles/getting-started/api-query-language#the-filter-section).
    google.protobuf.Struct filter = 1;
     // Sort object.
     //
     // Learn more about the [sort section](https://dev.wix.com/docs/rest/articles/getting-started/api-query-language#the-sort-section).
    repeated Sorting sort = 2 [(.wix.api.maxSize) = 5];
    reserved 3;
    reserved 4;
    reserved 5;
    oneof pagingMethod { 
        // Cursor paging options.
        //
        // Learn more about [cursor paging](https://dev.wix.com/docs/rest/articles/getting-started/api-query-language#cursor-paging).
        CursorPaging cursor_paging = 6;
    }
}

message Search {
    option (.wix.api.decomposite_of) = "wix.common.Search";
    option (.wix.api.decomposition_minimum_fields) = {
        field: "filter"
        field: "sort"
        field: "paging"
    };
    option (.wix.api.decomposition_minimum_fields) = {
        field: "filter"
        field: "sort"
        field: "cursor_paging"
    };
    // Filter object.
    //
    // Learn more about the [filter section](https://dev.wix.com/docs/rest/articles/getting-started/api-query-language#the-filter-section).
    google.protobuf.Struct filter = 1;
     // Sort object.
     //
     // Learn more about the [sort section](https://dev.wix.com/docs/rest/articles/getting-started/api-query-language#the-sort-section).
    repeated Sorting sort = 2 [(.wix.api.maxSize) = 10];
    // Projection on the result object - list of specific field names to return. If fieldsets are also specified, return the union of fieldsets and fields.
    repeated string fields = 3 [(.wix.api.maxLength) = 200, (.wix.api.maxSize) = 20];
    // Projection on the result object - list of named projections. For example, "basic" will return ID and name fields. Specifying multiple fieldsets will return the union of fields from all. Specifying fieldsets and fields will also return the union of fields.
    repeated string fieldsets = 4 [(.wix.api.maxLength) = 100, (.wix.api.maxSize) = 20];
    // Aggregations | Faceted search: refers to a way to explore large amounts of data by displaying summaries about various partitions of the data and later allowing to narrow the navigation to a specific partition.
    repeated Aggregation aggregations = 5 [(.wix.api.maxSize) = 10];
    // Free text to match in searchable fields.
    SearchDetails search = 6;
    oneof paging_method {
        // Pointer to page of results using offset. Can't be used together with 'cursor_paging'.
        Paging paging = 7;
        // Cursor pointing to page of results. Can't be used together with 'paging'. 'cursor_paging.cursor' can't be used together with 'filter' or 'sort'.
        CursorPaging cursor_paging = 8;
    }
    // UTC offset or IANA time zone. Valid values are
    // ISO 8601 UTC offsets, such as +02:00 or -06:00,
    // and IANA time zone IDs, such as Europe/Rome.
    //
    // Affects all filters and aggregations returned values.
    // You may override this behavior in a specific filter by providing
    // timestamps including time zone. For example, `"2023-12-20T10:52:34.795Z"`.
    google.protobuf.StringValue time_zone = 9 [(.wix.api.maxLength) = 50];
}

message CursorSearch {
    option (.wix.api.decomposite_of) = "wix.common.CursorSearch";
    // Filter object.
    //
    // Learn more about the [filter section](https://dev.wix.com/docs/rest/articles/getting-started/api-query-language#the-filter-section).
    google.protobuf.Struct filter = 1;
    // List of sort objects.
    //
    // Learn more about the [sort section](https://dev.wix.com/docs/rest/articles/getting-started/api-query-language#the-sort-section).
    repeated Sorting sort = 2 [(.wix.api.maxSize) = 10];
    reserved 3;
    reserved 4;
    reserved 7;
    // Aggregations are a way to explore large amounts of data by displaying summaries about various partitions of the data and later allowing to narrow the navigation to a specific partition.
    repeated Aggregation aggregations = 5 [(.wix.api.maxSize) = 10];
    // Free text to match in searchable fields.
    SearchDetails search = 6;
    oneof paging_method {
        // Cursor paging options.
        //
        // Learn more about [cursor paging](https://dev.wix.com/docs/rest/articles/getting-started/api-query-language#cursor-paging).
        CursorPaging cursor_paging = 8;
    }
    // UTC offset or IANA time zone. Valid values are
    // ISO 8601 UTC offsets, such as +02:00 or -06:00,
    // and IANA time zone IDs, such as Europe/Rome.
    //
    // Affects all filters and aggregations returned values.
    // You may override this behavior in a specific filter by providing
    // timestamps including time zone. For example, `"2023-12-20T10:52:34.795Z"`.
    google.protobuf.StringValue time_zone = 9 [(.wix.api.maxLength) = 50];
}

message SearchRelated {
    option (.wix.api.decomposite_of) = "wix.common.SearchRelated";
    // A list of entity IDs to search related entities for.
    repeated string related_to_ids = 1 [(.wix.api.minSize) = 1, (.wix.api.maxSize) = 10, (.wix.api.maxLength) = 50];
    // Search details.
    SearchRelatedDetails search = 2;
    // A filter object. See documentation [here](https://bo.wix.com/wix-docs/rnd/platformization-guidelines/api-query-language#platformization-guidelines_api-query-language_defining-in-protobuf)
    google.protobuf.Struct filter = 3;
    // Sort object in the form [{"fieldName":"sortField1"},{"fieldName":"sortField2","direction":"DESC"}].
    repeated Sorting sort = 4 [(.wix.api.maxSize) = 10];
    // Number of related documents to return.
    google.protobuf.Int32Value limit = 5 [(.wix.api.max) = 100];
}

message SearchRelatedDetails {
    option (.wix.api.decomposite_of) = "wix.common.SearchRelatedDetails";
    google.protobuf.StringValue expression = 2 [(.wix.api.maxLength) = 100]; // Search term or expression.
    // Fields to search in. If empty - will search in all searchable fields. Use dot notation to specify json path.
    repeated string fields = 3 [(.wix.api.maxLength) = 200, (.wix.api.maxSize) = 20];
}


message SearchDetails {
    option (.wix.api.decomposite_of) = "wix.common.SearchDetails";
    enum Mode {
        OR = 0; // Any of the search terms must be present.
        AND = 1; // All search terms must be present.
    }
    Mode mode = 1; // Defines how separate search terms in `expression` are combined.
    google.protobuf.StringValue expression = 2 [(.wix.api.maxLength) = 100]; // Search term or expression.
    // Fields to search in. If empty - will search in all searchable fields. Use dot notation to specify json path.
    repeated string fields = 3 [(.wix.api.maxLength) = 200, (.wix.api.maxSize) = 20];
    bool fuzzy = 4; // Whether to use auto fuzzy search (allowing typos by a managed proximity algorithm).
}

enum AggregationType {
    UNKNOWN_AGGREGATION_TYPE = 0 [(.wix.api.enum_maturity) = NOT_IMPLEMENTED];
    VALUE = 1; // An aggregation where result buckets are dynamically built - one per unique value.
    RANGE = 2; // An aggregation, where user can define set of ranges - each representing a bucket.
    SCALAR = 3; // A single-value metric aggregation. For example, min, max, sum, avg.
    DATE_HISTOGRAM = 4; // An aggregation, where result buckets are dynamically built - one per time interval (hour, day, week, etc.)
    NESTED = 5; // Multi-level aggregation, where each next aggregation is nested within previous one.
}

enum ScalarType {
    UNKNOWN_SCALAR_TYPE = 0 [(.wix.api.enum_maturity) = NOT_IMPLEMENTED];
    COUNT_DISTINCT = 1; // Count of distinct values.
    MIN = 2; // Minimum value.
    MAX = 3; // Maximum value.
    SUM = 4 [(.wix.api.enum_exposure) = PRIVATE]; // Sum of values.
    AVG = 5 [(.wix.api.enum_exposure) = PRIVATE]; // Average of values.
}

message Aggregation {
    option (.wix.api.decomposite_of) = "wix.common.Aggregation";
    message RangeAggregation {
        option (.wix.api.decomposite_of) = "wix.common.Aggregation.RangeAggregation";
        message RangeBucket {
            option (.wix.api.decomposite_of) = "wix.common.Aggregation.RangeAggregation.RangeBucket";
            google.protobuf.DoubleValue from = 1; // Inclusive lower bound of the range. Required if `to` is not provided.
            google.protobuf.DoubleValue to = 2; // Exclusive upper bound of the range. Required if `from` is not provided.
        }
        // List of range buckets, where during aggregation each entity will be placed in the first bucket its value falls into, based on the provided range bounds.
        repeated RangeBucket buckets = 1 [(.wix.api.maxSize) = 50];
    }

    message ValueAggregation {
        option (.wix.api.decomposite_of) = "wix.common.Aggregation.ValueAggregation";
        enum SortType {
            COUNT = 0; // Sort by number of matches.
            VALUE = 1; // Sort by value of the field alphabetically.
        }
        enum SortDirection {
            DESC = 0; // Sort in descending order.
            ASC = 1; // Sort in ascending order.
        }

        enum MissingValues {
            EXCLUDE = 0; // Exclude missing values from the aggregation results.
            INCLUDE = 1; // Include missing values in the aggregation results.
        }

        message IncludeMissingValuesOptions {
            option (.wix.api.decomposite_of) = "wix.common.Aggregation.ValueAggregation.IncludeMissingValuesOptions";
            string add_to_bucket = 1 [(.wix.api.maxLength) = 20]; // Specify custom bucket name. Defaults are [string -> "N/A"], [int -> "0"], [bool -> "false"] ...
        }

        SortType sort_type = 1; // Whether to sort by number of matches or value of the field.
        SortDirection sort_direction = 2; // Whether to sort in ascending or descending order.
        google.protobuf.Int32Value limit = 3; // How many aggregations to return. Can be between 1 and 250. 10 is the default.

        MissingValues missing_values = 4; // Whether to include or exclude missing values from the aggregation results. Default: `EXCLUDE`.
        oneof options {
            option (.wix.api.aligned_with_enum).field = "missing_values";
            IncludeMissingValuesOptions include_options = 5; // Options for including missing values.
        }
    }

    message ScalarAggregation {
        option (.wix.api.decomposite_of) = "wix.common.Aggregation.ScalarAggregation";
        ScalarType type = 1; // Define the operator for the scalar aggregation.
    }

    message GroupByAggregation {
        option (.wix.api.decomposite_of) = "wix.common.Aggregation.GroupByAggregation";
        google.protobuf.StringValue name = 1 [(.wix.api.maxLength) = 100]; // User-defined name of aggregation, should be unique, will appear in aggregation results.
        string field_path = 3 [(.wix.api.maxLength) = 200]; // Field to aggregate by.
        oneof kind {
            ValueAggregation value = 4; // Value aggregation configuration.
        }
    }

    // Nested aggregation expressed through a list of aggregation where each next aggregation is nested within previous one.
    message NestedAggregation {
        option (.wix.api.decomposite_of) = "wix.common.Aggregation.NestedAggregation";
        reserved 1;

        enum NestedAggregationType {
            UNKNOWN_AGGREGATION_TYPE = 0 [(.wix.api.enum_maturity) = NOT_IMPLEMENTED];
            VALUE = 1; // An aggregation where result buckets are dynamically built - one per unique value.
            RANGE = 2; // An aggregation, where user can define set of ranges - each representing a bucket.
            SCALAR = 3; // A single-value metric aggregation. For example, min, max, sum, avg.
            DATE_HISTOGRAM = 4; // An aggregation, where result buckets are dynamically built - one per time interval (hour, day, week, etc.).
        }

        message NestedAggregationItem {
            option (.wix.api.decomposite_of) = "wix.common.Aggregation.NestedAggregation.NestedAggregationItem";
            google.protobuf.StringValue name = 1 [(.wix.api.maxLength) = 100]; // User-defined name of aggregation, should be unique, will appear in aggregation results.
            NestedAggregationType type = 2; // Type of aggregation, client must provide matching aggregation field below.
            string field_path = 3 [(.wix.api.maxLength) = 200]; // Field to aggregate by, use dot notation to specify json path.
            oneof kind {
                ValueAggregation value = 4; // Value aggregation.
                RangeAggregation range = 5; // Range aggregation.
                ScalarAggregation scalar = 6; // Scalar aggregation.
                DateHistogramAggregation date_histogram = 9; // Date histogram aggregation.
            }
        }

        // Flattened list of aggregations, where each next aggregation is nested within previous one.
        repeated NestedAggregationItem nested_aggregations = 2 [(.wix.api.minSize) = 2, (.wix.api.maxSize) = 3];
    }

    message DateHistogramAggregation {
        option (.wix.api.decomposite_of) = "wix.common.Aggregation.DateHistogramAggregation";
        enum Interval {
            UNKNOWN_INTERVAL = 0 [(.wix.api.enum_maturity) = NOT_IMPLEMENTED];
            YEAR = 1; // Yearly interval
            MONTH = 2; // Monthly interval
            WEEK = 3; // Weekly interval
            DAY = 4; // Daily interval
            HOUR = 5; // Hourly interval
            MINUTE = 6; // Minute interval
            SECOND = 7; // Second interval
        }

        Interval interval = 1; // Interval for date histogram aggregation.
    }

    google.protobuf.StringValue name = 1 [(.wix.api.maxLength) = 100]; // User-defined name of aggregation, should be unique, will appear in aggregation results.
    AggregationType type = 2; // Type of aggregation, client must provide matching aggregation field below.
    string field_path = 3 [(.wix.api.maxLength) = 200]; // Field to aggregate by, use dot notation to specify json path.
    oneof kind {
        ValueAggregation value = 4; // Value aggregation.
        RangeAggregation range = 5; // Range aggregation.
        ScalarAggregation scalar = 6; // Scalar aggregation.
        DateHistogramAggregation date_histogram = 9; // Date histogram aggregation.
        NestedAggregation nested = 8; // Nested aggregation.
    }

}

message AggregationData {
    option (.wix.api.decomposite_of) = "wix.common.AggregationData";
    message AggregationResults {
        option (.wix.api.decomposite_of) = "wix.common.AggregationData.AggregationResults";
        message ValueResults {
            option (.wix.api.decomposite_of) = "wix.common.AggregationData.AggregationResults.ValueResults";
            message ValueAggregationResult {
                option (.wix.api.decomposite_of) = "wix.common.AggregationData.AggregationResults.ValueResults.ValueAggregationResult";
                string value = 1 [(.wix.api.maxLength) = 100]; // Value of the field.
                int32 count = 2; // Count of entities with this value.
            }
            repeated ValueAggregationResult results = 1 [(.wix.api.maxSize) = 250]; // List of value aggregations.
        }

        message RangeResults {
            option (.wix.api.decomposite_of) = "wix.common.AggregationData.AggregationResults.RangeResults";
            message RangeAggregationResult {
                option (.wix.api.decomposite_of) = "wix.common.AggregationData.AggregationResults.RangeResults.RangeAggregationResult";
                google.protobuf.DoubleValue from = 1; // Inclusive lower bound of the range.
                google.protobuf.DoubleValue to = 2; // Exclusive upper bound of the range.
                int32 count = 3; // Count of entities in this range.
            }
            repeated RangeAggregationResult results = 1 [(.wix.api.maxSize) = 50]; // List of ranges returned in same order as requested.
        }

        message ScalarResult {
            option (.wix.api.decomposite_of) = "wix.common.AggregationData.AggregationResults.ScalarResult";
            ScalarType type = 1; // Type of scalar aggregation.
            double value = 2; // Value of the scalar aggregation.
        }

        message GroupByValueResults {
            option (.wix.api.decomposite_of) = "wix.common.AggregationData.AggregationResults.GroupByValueResults";
            message NestedValueAggregationResult {
                option (.wix.api.decomposite_of) = "wix.common.AggregationData.AggregationResults.GroupByValueResults.NestedValueAggregationResult";
                string value = 1 [(.wix.api.maxLength) = 1000]; // Value of the field.
                NestedAggregationResults nested_results = 2; // Nested aggregations.

            }
            repeated NestedValueAggregationResult results = 1 [(.wix.api.maxSize) = 1000]; // List of value aggregations.
        }

        message NestedAggregationResults {
            option (.wix.api.decomposite_of) = "wix.common.AggregationData.AggregationResults.NestedAggregationResults";
            string name = 1 [(.wix.api.maxLength) = 100]; // User-defined name of aggregation, matches the one provided in request.
            AggregationType type = 2; // Type of aggregation that matches result.
            string field_path = 6 [(.wix.api.maxLength) = 200]; // Field to aggregate by, matches the one provided in request.
            oneof result {
                ValueResults values = 3; // Value aggregation results.
                RangeResults ranges = 4; // Range aggregation results.
                ScalarResult scalar = 5; // Scalar aggregation results.
            }
        }

        // Results of `NESTED` aggregation type in a flattened form.
        // Aggregations in resulting array are keyed by requested aggregation `name`.
        message NestedResults {
            option (.wix.api.decomposite_of) = "wix.common.AggregationData.AggregationResults.NestedResults";
            message ValueResult {
                option (.wix.api.decomposite_of) = "wix.common.AggregationData.AggregationResults.NestedResults.ValueResult";
                string value = 1 [(.wix.api.maxLength) = 1000]; // Value of the field.
                google.protobuf.Int32Value count = 2; // Count of entities with this value.
            }
            message RangeResult {
                option (.wix.api.decomposite_of) = "wix.common.AggregationData.AggregationResults.NestedResults.RangeResult";
                google.protobuf.DoubleValue from = 1; // Inclusive lower bound of the range.
                google.protobuf.DoubleValue to = 2; // Exclusive upper bound of the range.
                google.protobuf.Int32Value count = 3; // Count of entities in this range.
            }

            message ScalarResult {
                option (.wix.api.decomposite_of) = "wix.common.AggregationData.AggregationResults.NestedResults.ScalarResult";
                double value = 1; // Value of the scalar aggregation.
            }

            message NestedResultValue {
                option (.wix.api.decomposite_of) = "wix.common.AggregationData.AggregationResults.NestedResults.NestedResultValue";
                oneof result {
                    ValueResult value = 1; // Value aggregation result.
                    RangeResult range = 2; // Range aggregation result.
                    ScalarResult scalar = 3; // Scalar aggregation result.
                    ValueResult date_histogram = 4; // Date histogram aggregation result.
                }
            }

            message Results {
                option (.wix.api.decomposite_of) = "wix.common.AggregationData.AggregationResults.NestedResults.Results";
                map<string, NestedResultValue> results = 1; // List of nested aggregations.
            }

            repeated Results results = 1 [(.wix.api.maxSize) = 1000]; // List of nested aggregations.
        }

        message DateHistogramResults {
            option (.wix.api.decomposite_of) = "wix.common.AggregationData.AggregationResults.DateHistogramResults";
            message DateHistogramResult {
                option (.wix.api.decomposite_of) = "wix.common.AggregationData.AggregationResults.DateHistogramResults.DateHistogramResult";
                string value = 1 [(.wix.api.maxLength) = 100]; // Date in ISO 8601 format.
                int32 count = 2; // Count of documents in the bucket.
            }
            repeated DateHistogramResult results = 1 [(.wix.api.maxSize) = 200]; // List of date histogram aggregations.
        }

        string name = 1 [(.wix.api.maxLength) = 100]; // User-defined name of aggregation as derived from search request.
        AggregationType type = 2; // Type of aggregation that must match provided kind as derived from search request.
        string field_path = 6 [(.wix.api.maxLength) = 200]; // Field to aggregate by as derived from search request.
        oneof result {
            ValueResults values = 3; // Value aggregation results.
            RangeResults ranges = 4; // Range aggregation results.
            ScalarResult scalar = 5; // Scalar aggregation results.
            GroupByValueResults grouped_by_value = 7; // Group by value aggregation results.
            DateHistogramResults date_histogram = 8; // Date histogram aggregation results.
            NestedResults nested = 9; // Nested aggregation results.
        }
    }

    repeated AggregationResults results = 1 [(.wix.api.maxSize) = 10000]; // key = aggregation name (as derived from search request).
}

/*
// Usage example in response composition:
message ProductSearchResponse {
    option (.wix.api.decomposite_of) = "wix.common.ProductSearchResponse";
    AggregationData aggregations = 1;
    PagingMetadataV2 metadata = 2;
    repeated Product products = 3;
}

// example Value type Request:
{
    search: {
        expression: "term"
    },
    aggregations: [
        {
            name: "my-value-aggregation",
            type: "VALUE",
            fieldPath: "path.to.field",
            value: {
                sort_type: "VALUE",
                sort_direction: "DESC",
                limit: 15
            }
        }
    ]
}

// example Value type Response:
{
    aggregations: {
        results: [
            {
                name: "my-value-aggregation",
                type: "VALUE",
                values: {
                    results: [
                        {
                            value: "v1",
                            count: 9
                        },
                        {
                            value: "v2",
                            count: 6
                        }
                    ]
                }
            }
        ]
    },
    metadata: {
      items: 25,
      offset: 25,
      total: 420,
      tooManyToCount: false,
      cursors: {
        next: "SOMEHASHFORNEXT",
        prev: "SOMEHASHFORPREV"
      }
    },
    products: [...]
}

// example Range type Request:
{
    search: {
        expression: "term"
    },
    aggregations: [
        {
            name: "my-range-aggregation",
            type: "RANGE",
            fieldPath: "path.to.field",
            range: {
                buckets: [
                    {
                        to: 10
                    },
                    {
                        from: 10,
                        to: 20
                    },
                    {
                        from: 20
                    }
                ]
            }
        }
    ]
}

// example Range type Response:
{
    aggregations: {
        results: [
            {
                name: "my-range-aggregation",
                type: "RANGE",
                ranges: {
                    results: [
                        {
                            to: 10,
                            count: 5
                        },
                        {
                            from: 10,
                            to: 20,
                            count: 3
                        },
                        {
                            from: 20,
                            count: 1
                        }
                    ]
                }
            }
        ]
    },
    metadata: {
        items: 25,
        offset: 25,
        total: 420,
        tooManyToCount: false,
        cursors: {
          next: "SOMEHASHFORNEXT",
          prev: "SOMEHASHFORPREV"
        }
      },
      products: [...]
}

// example Scalar type Request:
{
    search: {
        expression: "term"
    },
    aggregations: [
        {
            name: "my-scalar-aggregation",
            type: "SCALAR",
            fieldPath: "path.to.field",
            scalar: {
                type: "AVG"
            }
        }
    ]
}

// example Scalar type Response:
{
    aggregations: {
        results: [
            {
                name: "my-scalar-agregation",
                type: "SCALAR",
                scalar: {
                    type: "AVG",
                    value: 5.555
                }
            }
        ]
    },
    metadata: {
        items: 25,
        offset: 25,
        total: 420,
        tooManyToCount: false,
        cursors: {
          next: "SOMEHASHFORNEXT",
          prev: "SOMEHASHFORPREV"
        }
      },
      products: [...]
}

// example Group By Aggregation Request:
{
  "filter" : {
    "region" : "EU"
  },
  "aggregations" : [ {
    "name" : "production countries",
    "type" : "VALUE",
    "fieldPath" : "production_countries",
    "value" : {
      "limit" : 5
    },
    "groupBy" : {
      "name" : "production companies",
      "fieldPath" : "production_companies",
      "value" : { }
    }
  } ]
}

// example Group By Aggregation Response:
{
  "aggregations" : {
    "results" : [ {
      "name" : "production companies",
      "type" : "VALUE",
      "fieldPath" : "production_companies",
      "groupedByValue" : {
        "results" : [ {
          "value" : "Warner Bros.",
          "nestedResults" : {
            "name" : "production countries",
            "type" : "VALUE",
            "fieldPath" : "production_countries",
            "values" : {
              "results" : [ {
                "value" : "GB",
                "count" : 221
              }, {
                "value" : "PL",
                "count" : 12
              } ]
            }
          }
        }, {
          "value" : "Metro-Goldwyn-Mayer (MGM)",
          "nestedResults" : {
            "name" : "production countries",
            "type" : "VALUE",
            "fieldPath" : "production_countries",
            "values" : {
              "results" : [ {
                "value" : "SWE",
                "count" : 24
              }, {
                "value" : "FR",
                "count" : 18
              }, {
                "value" : "LT",
                "count" : 2
              } ]
            }
          }
        } ]
      }
    } ]
  }
}

// example of 2-level nested aggregation request:
{
  "filter" : {
    "region" : "EU"
  },
  "aggregations" : [ {
    "name" : "my nested",
    "type" : "NESTED",
    "nested" : {
      "nestedAggregations" : [ {
        "name" : "daily",
        "type" : "DATE_HISTOGRAM",
        "fieldPath" : "date_updated",
        "dateHistogram" : {
          "interval" : "DAY"
        }
      }, {
        "name" : "inventory status",
        "type" : "VALUE",
        "fieldPath" : "status",
        "value" : { }
      }, {
        "name" : "sum",
        "type" : "SCALAR",
        "fieldPath" : "price",
        "scalar" : {
          "type" : "SUM"
        }
      } ]
    }
  } ]
}

// example of 2-level nested aggregation response:
{
  "aggregations" : {
    "results" : [ {
      "name" : "my nested",
      "type" : "NESTED",
      "fieldPath" : "DUNNO WHAT TO DO WITH THIS",
      "nested" : {
        "results" : [ {
          "results" : {
            "daily" : {
              "dateHistogram" : {
                "value" : "2023.1.1"
              }
            },
            "inventory status" : {
              "value" : {
                "value" : "SOLD",
                "count" : 12
              }
            },
            "sum" : {
              "scalar" : {
                "value" : 10.0
              }
            }
          }
        }, {
          "results" : {
            "daily" : {
              "dateHistogram" : {
                "value" : "2023.1.1"
              }
            },
            "inventory status" : {
              "value" : {
                "value" : "NOT-SOLD",
                "count" : 13
              }
            },
            "sum" : {
              "scalar" : {
                "value" : 5.0
              }
            }
          }
        }, {
          "results" : {
            "daily" : {
              "dateHistogram" : {
                "value" : "2023.1.2"
              }
            },
            "inventory status" : {
              "value" : {
                "value" : "SOLD",
                "count" : 5
              }
            },
            "sum" : {
              "scalar" : {
                "value" : 10.0
              }
            }
          }
        }, {
          "results" : {
            "daily" : {
              "dateHistogram" : {
                "value" : "2023.1.2"
              }
            },
            "inventory status" : {
              "value" : {
                "value" : "NOT-SOLD",
                "count" : 7
              }
            },
            "sum" : {
              "scalar" : {
                "value" : 10.0
              }
            }
          }
        } ]
      }
    } ]
  }
}

*/
