{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$ref": "#/definitions/SCSearchQuery",
  "description": "A search request",
  "definitions": {
    "SCSearchQuery": {
      "type": "object",
      "properties": {
        "context": {
          "$ref": "#/definitions/SCSearchContext",
          "description": "The context name from where the search query was initiated"
        },
        "filter": {
          "$ref": "#/definitions/SCSearchFilter",
          "description": "A filter structure that combines any number of filters with boolean methods ('AND', 'OR', 'NOT')"
        },
        "from": {
          "type": "number",
          "description": "Number of things to skip in result set (paging)"
        },
        "query": {
          "type": "string",
          "description": "A term to search for"
        },
        "size": {
          "type": "number",
          "description": "Number of things to have in the result set (paging)"
        },
        "sort": {
          "type": "array",
          "items": {
            "$ref": "#/definitions/SCSearchSort"
          },
          "description": "A list of sorting parameters to order the result set by"
        }
      },
      "additionalProperties": false,
      "description": "A search query"
    },
    "SCSearchContext": {
      "type": "string",
      "enum": [
        "default",
        "dining",
        "place"
      ],
      "description": "Possible context names to be used by the search request"
    },
    "SCSearchFilter": {
      "anyOf": [
        {
          "$ref": "#/definitions/SCSearchAvailabilityFilter"
        },
        {
          "$ref": "#/definitions/SCSearchBooleanFilter"
        },
        {
          "$ref": "#/definitions/SCSearchDistanceFilter"
        },
        {
          "$ref": "#/definitions/SCSearchValueFilter"
        },
        {
          "$ref": "#/definitions/SCSearchNumericRangeFilter"
        },
        {
          "$ref": "#/definitions/SCSearchDateRangeFilter"
        },
        {
          "$ref": "#/definitions/SCGeoFilter"
        }
      ],
      "description": "Available filter instructions"
    },
    "SCSearchAvailabilityFilter": {
      "type": "object",
      "properties": {
        "arguments": {
          "$ref": "#/definitions/SCAvailabilityFilterArguments",
          "description": "Arguments of filter"
        },
        "type": {
          "type": "string",
          "const": "availability",
          "description": "Type of filter"
        }
      },
      "required": [
        "arguments",
        "type"
      ],
      "additionalProperties": false,
      "description": "An availability filter\n\nFilter for documents where it cannot be safely determined that they are not available"
    },
    "SCAvailabilityFilterArguments": {
      "type": "object",
      "properties": {
        "field": {
          "$ref": "#/definitions/SCThingsField",
          "description": "Field which marks availability range"
        },
        "scope": {
          "type": "string",
          "enum": [
            "s",
            "m",
            "H",
            "d",
            "w",
            "M",
            "y"
          ],
          "description": "If set, the provided time will apply to the full hour, day, week, etc."
        },
        "time": {
          "$ref": "#/definitions/SCISO8601Date",
          "description": "Time to check. Defaults current time if not set"
        }
      },
      "required": [
        "field"
      ],
      "additionalProperties": {
        "description": "One value for each key"
      },
      "description": "Arguments for filter instruction by availability"
    },
    "SCThingsField": {
      "type": "string",
      "description": "A field of a thing"
    },
    "SCISO8601Date": {
      "type": "string",
      "description": "An ISO8601 date",
      "pattern": "^(-?(?:[1-9][0-9]*)?[0-9]{4})-(1[0-2]|0[1-9])-(3[01]|0[1-9]|[12][0-9])(T(2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9])([\\.,][0-9]{0,7})?(Z|[+-](?:2[0-3]|[01][0-9])(:?[0-5][0-9])?)?)?$"
    },
    "SCSearchBooleanFilter": {
      "type": "object",
      "properties": {
        "arguments": {
          "$ref": "#/definitions/SCBooleanFilterArguments",
          "description": "Arguments of filter"
        },
        "type": {
          "type": "string",
          "const": "boolean",
          "description": "Type of filter"
        }
      },
      "required": [
        "arguments",
        "type"
      ],
      "additionalProperties": false,
      "description": "A boolean filter\n\nThis filter can be used to combine multiple filters with boolean operations."
    },
    "SCBooleanFilterArguments": {
      "type": "object",
      "properties": {
        "filters": {
          "type": "array",
          "items": {
            "$ref": "#/definitions/SCSearchFilter"
          },
          "description": "A list of filter to apply the boolean operation to"
        },
        "operation": {
          "type": "string",
          "enum": [
            "and",
            "not",
            "or"
          ],
          "description": "Boolean operation to apply to the filters"
        }
      },
      "required": [
        "filters",
        "operation"
      ],
      "additionalProperties": {
        "description": "One value for each key"
      },
      "description": "Additional arguments for boolean filters"
    },
    "SCSearchDistanceFilter": {
      "type": "object",
      "properties": {
        "arguments": {
          "$ref": "#/definitions/SCDistanceFilterArguments",
          "description": "Arguments of filter"
        },
        "type": {
          "type": "string",
          "const": "distance",
          "description": "Type of filter"
        }
      },
      "required": [
        "arguments",
        "type"
      ],
      "additionalProperties": false,
      "description": "A distance filter\n\nFilter for documents that are in the given distance of the given location"
    },
    "SCDistanceFilterArguments": {
      "type": "object",
      "properties": {
        "distance": {
          "type": "number",
          "description": "Distance in meters to filter from given location"
        },
        "field": {
          "$ref": "#/definitions/SCThingsField",
          "description": "Field which contains the location you want to filter"
        },
        "position": {
          "$ref": "#/definitions/Position",
          "description": "Position to calculate the distance to"
        }
      },
      "required": [
        "distance",
        "field",
        "position"
      ],
      "additionalProperties": {
        "description": "One value for each key"
      },
      "description": "Additional arguments for distance filters"
    },
    "Position": {
      "type": "array",
      "items": {
        "type": "number"
      },
      "description": "* http://geojson.org/geojson-spec.html#positions"
    },
    "SCSearchValueFilter": {
      "type": "object",
      "properties": {
        "arguments": {
          "$ref": "#/definitions/SCValueFilterArguments",
          "description": "Arguments of filter"
        },
        "type": {
          "type": "string",
          "const": "value",
          "description": "Type of filter"
        }
      },
      "required": [
        "arguments",
        "type"
      ],
      "additionalProperties": false,
      "description": "Filters for documents that match the value on the given field"
    },
    "SCValueFilterArguments": {
      "type": "object",
      "properties": {
        "field": {
          "$ref": "#/definitions/SCThingsField",
          "description": "Field to filter for a value."
        },
        "value": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "array",
              "items": {
                "type": "string"
              }
            }
          ],
          "description": "Value to filter. One or more values has to match the field exactly.\n\nLeaving the value out will check if the field exists."
        }
      },
      "required": [
        "field"
      ],
      "additionalProperties": {
        "description": "One value for each key"
      }
    },
    "SCSearchNumericRangeFilter": {
      "type": "object",
      "properties": {
        "arguments": {
          "$ref": "#/definitions/SCNumericRangeFilterArguments",
          "description": "Arguments of filter"
        },
        "type": {
          "type": "string",
          "const": "numeric range",
          "description": "Type of filter"
        }
      },
      "required": [
        "arguments",
        "type"
      ],
      "additionalProperties": false,
      "description": "A distance filter\n\nFilter for documents with a numeric field that satisfies the given constraints"
    },
    "SCNumericRangeFilterArguments": {
      "$ref": "#/definitions/SCRangeFilterArguments%3Cnumber%3E",
      "description": "Additional arguments for numeric range filters"
    },
    "SCRangeFilterArguments<number>": {
      "type": "object",
      "properties": {
        "bounds": {
          "$ref": "#/definitions/Bounds%3Cnumber%3E",
          "description": "Bounds of the range"
        },
        "field": {
          "$ref": "#/definitions/SCThingsField",
          "description": "Field where the filter will be applied"
        },
        "relation": {
          "type": "string",
          "enum": [
            "intersects",
            "within",
            "contains"
          ],
          "description": "Relation when searching on other range fields\n\nIntersects (Default): Both search and field range intersect Within: Search range is within the field range Contains: Search range contains the field range"
        }
      },
      "required": [
        "bounds",
        "field"
      ],
      "additionalProperties": {
        "description": "One value for each key"
      },
      "description": "Additional arguments for range filters"
    },
    "Bounds<number>": {
      "type": "object",
      "properties": {
        "lowerBound": {
          "$ref": "#/definitions/Bound%3Cnumber%3E",
          "description": "The lower bound"
        },
        "upperBound": {
          "$ref": "#/definitions/Bound%3Cnumber%3E",
          "description": "The upper bound"
        }
      },
      "additionalProperties": false
    },
    "Bound<number>": {
      "type": "object",
      "properties": {
        "limit": {
          "type": "number",
          "description": "Limit of the bound"
        },
        "mode": {
          "type": "string",
          "enum": [
            "inclusive",
            "exclusive"
          ],
          "description": "Bound mode"
        }
      },
      "required": [
        "limit",
        "mode"
      ],
      "additionalProperties": false
    },
    "SCSearchDateRangeFilter": {
      "type": "object",
      "properties": {
        "arguments": {
          "$ref": "#/definitions/SCDateRangeFilterArguments",
          "description": "Arguments of filter"
        },
        "type": {
          "type": "string",
          "const": "date range",
          "description": "Type of filter"
        }
      },
      "required": [
        "arguments",
        "type"
      ],
      "additionalProperties": false,
      "description": "A date range filter\n\nFilter for documents with a date field that satisfies the given constraints"
    },
    "SCDateRangeFilterArguments": {
      "type": "object",
      "properties": {
        "bounds": {
          "$ref": "#/definitions/Bounds%3Cstring%3E",
          "description": "Bounds of the range"
        },
        "field": {
          "$ref": "#/definitions/SCThingsField",
          "description": "Field where the filter will be applied"
        },
        "relation": {
          "type": "string",
          "enum": [
            "intersects",
            "within",
            "contains"
          ],
          "description": "Relation when searching on other range fields\n\nIntersects (Default): Both search and field range intersect Within: Search range is within the field range Contains: Search range contains the field range"
        },
        "format": {
          "type": "string",
          "description": "Optional date format specifier"
        },
        "timeZone": {
          "type": "string",
          "description": "Optional timezone specifier"
        }
      },
      "additionalProperties": {
        "description": "One value for each key"
      },
      "required": [
        "bounds",
        "field"
      ],
      "description": "Additional arguments for date range filters\n\nFilter uses a plain string to allow for date math expressions"
    },
    "Bounds<string>": {
      "type": "object",
      "properties": {
        "lowerBound": {
          "$ref": "#/definitions/Bound%3Cstring%3E",
          "description": "The lower bound"
        },
        "upperBound": {
          "$ref": "#/definitions/Bound%3Cstring%3E",
          "description": "The upper bound"
        }
      },
      "additionalProperties": false
    },
    "Bound<string>": {
      "type": "object",
      "properties": {
        "limit": {
          "type": "string",
          "description": "Limit of the bound"
        },
        "mode": {
          "type": "string",
          "enum": [
            "inclusive",
            "exclusive"
          ],
          "description": "Bound mode"
        }
      },
      "required": [
        "limit",
        "mode"
      ],
      "additionalProperties": false
    },
    "SCGeoFilter": {
      "type": "object",
      "properties": {
        "arguments": {
          "$ref": "#/definitions/SCGeoFilterArguments",
          "description": "Arguments of filter"
        },
        "type": {
          "type": "string",
          "const": "geo",
          "description": "Type of filter"
        }
      },
      "required": [
        "arguments",
        "type"
      ],
      "additionalProperties": false,
      "description": "A geo filter\n\nFilter for documents that are in relation to some geo data"
    },
    "SCGeoFilterArguments": {
      "type": "object",
      "properties": {
        "field": {
          "$ref": "#/definitions/SCThingsField",
          "description": "Field on which to filter"
        },
        "shape": {
          "anyOf": [
            {
              "$ref": "#/definitions/Polygon"
            },
            {
              "$ref": "#/definitions/Envelope"
            }
          ],
          "description": "Geo data to check up on"
        },
        "spatialRelation": {
          "type": "string",
          "enum": [
            "intersects",
            "disjoint",
            "within",
            "contains"
          ],
          "description": "Spatial relation between the provided shape and the shape of the field.\n\nintersects - both shapes intersect (default) disjoint   - both shapes don't intersect within     - the search shape contains the field shape contains   - the search shape is contained in the field shape"
        }
      },
      "required": [
        "field",
        "shape"
      ],
      "additionalProperties": {
        "description": "One value for each key"
      },
      "description": "Arguments for filter instruction by geo data"
    },
    "Polygon": {
      "type": "object",
      "properties": {
        "type": {
          "type": "string",
          "const": "Polygon"
        },
        "bbox": {
          "type": "array",
          "items": {
            "type": "number"
          }
        },
        "crs": {
          "$ref": "#/definitions/CoordinateReferenceSystem"
        },
        "coordinates": {
          "type": "array",
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/definitions/Position"
            }
          }
        }
      },
      "required": [
        "coordinates",
        "type"
      ],
      "additionalProperties": false,
      "description": "* http://geojson.org/geojson-spec.html#polygon"
    },
    "CoordinateReferenceSystem": {
      "type": "object",
      "properties": {
        "type": {
          "type": "string"
        },
        "properties": {}
      },
      "required": [
        "type",
        "properties"
      ],
      "additionalProperties": false,
      "description": "* http://geojson.org/geojson-spec.html#coordinate-reference-system-objects"
    },
    "Envelope": {
      "type": "object",
      "properties": {
        "coordinates": {
          "type": "array",
          "items": {
            "$ref": "#/definitions/Position"
          },
          "minItems": 2,
          "maxItems": 2,
          "description": "The top-left and bottom-right corners of the bounding box"
        },
        "type": {
          "type": "string",
          "const": "envelope",
          "description": "The type of the geometry"
        }
      },
      "required": [
        "coordinates",
        "type"
      ],
      "additionalProperties": false,
      "description": "A rectangular geo shape, representing the top-left and bottom-right corners\n\nThis is an extension of the Geojson type http://geojson.org/geojson-spec.html"
    },
    "SCSearchSort": {
      "anyOf": [
        {
          "$ref": "#/definitions/SCDistanceSort"
        },
        {
          "$ref": "#/definitions/SCPriceSort"
        },
        {
          "$ref": "#/definitions/SCDucetSort"
        },
        {
          "$ref": "#/definitions/SCGenericSort"
        }
      ],
      "description": "A sort instruction"
    },
    "SCDistanceSort": {
      "type": "object",
      "properties": {
        "arguments": {
          "$ref": "#/definitions/SCDistanceSortArguments",
          "description": "Map of arguments for the sort instruction"
        },
        "order": {
          "type": "string",
          "enum": [
            "asc",
            "desc"
          ],
          "description": "Direction of the sort instruction: `asc`ending or `desc`ending."
        },
        "type": {
          "type": "string",
          "const": "distance",
          "description": "Type of the sort instruction"
        }
      },
      "required": [
        "arguments",
        "order",
        "type"
      ],
      "additionalProperties": false,
      "description": "Sort instruction to sort by distance"
    },
    "SCDistanceSortArguments": {
      "type": "object",
      "properties": {
        "field": {
          "$ref": "#/definitions/SCThingsField",
          "description": "Field to sort by"
        },
        "position": {
          "$ref": "#/definitions/Position",
          "description": "Position to calculate distances to"
        }
      },
      "required": [
        "field",
        "position"
      ],
      "additionalProperties": {
        "description": "One value for each key"
      },
      "description": "Additional arguments for sort instruction to sort by distance"
    },
    "SCPriceSort": {
      "type": "object",
      "properties": {
        "arguments": {
          "$ref": "#/definitions/SCPriceSortArguments",
          "description": "Map of arguments for the sort instruction"
        },
        "order": {
          "type": "string",
          "enum": [
            "asc",
            "desc"
          ],
          "description": "Direction of the sort instruction: `asc`ending or `desc`ending."
        },
        "type": {
          "type": "string",
          "const": "price",
          "description": "Type of the sort instruction"
        }
      },
      "required": [
        "arguments",
        "order",
        "type"
      ],
      "additionalProperties": false,
      "description": "Sort instruction to sort by price"
    },
    "SCPriceSortArguments": {
      "type": "object",
      "properties": {
        "field": {
          "$ref": "#/definitions/SCThingsField",
          "description": "Field to sort by"
        },
        "universityRole": {
          "type": "string",
          "enum": [
            "alumni",
            "employee",
            "guest",
            "student",
            "default"
          ],
          "description": "University role to sort price for"
        }
      },
      "required": [
        "field",
        "universityRole"
      ],
      "additionalProperties": {
        "description": "One value for each key"
      },
      "description": "Additional arguments for sort instruction to sort by price"
    },
    "SCDucetSort": {
      "type": "object",
      "properties": {
        "arguments": {
          "$ref": "#/definitions/SCSearchAbstractSortArguments",
          "description": "Map of arguments for the sort instruction"
        },
        "order": {
          "type": "string",
          "enum": [
            "asc",
            "desc"
          ],
          "description": "Direction of the sort instruction: `asc`ending or `desc`ending."
        },
        "type": {
          "type": "string",
          "const": "ducet",
          "description": "Type of the sort instruction"
        }
      },
      "required": [
        "arguments",
        "order",
        "type"
      ],
      "additionalProperties": false,
      "description": "Sort instruction for ducet sort"
    },
    "SCSearchAbstractSortArguments": {
      "type": "object",
      "properties": {
        "field": {
          "$ref": "#/definitions/SCThingsField",
          "description": "Field to sort by"
        }
      },
      "required": [
        "field"
      ],
      "additionalProperties": {
        "description": "One value for each key"
      },
      "description": "Map of arguments for the sort instruction"
    },
    "SCGenericSort": {
      "type": "object",
      "properties": {
        "arguments": {
          "$ref": "#/definitions/SCSearchAbstractSortArguments",
          "description": "Map of arguments for the sort instruction"
        },
        "order": {
          "type": "string",
          "enum": [
            "asc",
            "desc"
          ],
          "description": "Direction of the sort instruction: `asc`ending or `desc`ending."
        },
        "type": {
          "type": "string",
          "const": "generic",
          "description": "Type of the sort instruction"
        }
      },
      "required": [
        "arguments",
        "order",
        "type"
      ],
      "additionalProperties": false,
      "description": "Sort instruction for generic sort such as date"
    },
    "SCSCSearchRequest": {
      "$ref": "#/definitions/SCSearchQuery",
      "description": "A search request"
    }
  },
  "$id": "https://core.stapps.tu-berlin.de/v4.0.2/lib/schema/SCSearchRequest.json"
}