Mapbox Tiling Service
Beta

Recipe specification

Current version: 1

A tileset recipe is a JSON document composed of configuration options that tell Mapbox Tiling Service (MTS) how to turn tileset source data into vector tiles.

When writing rules in a recipe document, you can use expressions or base them on the properties in your data. Example rules that you might specify in a recipe document could include:

  • Tile uploaded tornado data from zooms 5 through 16.
  • Only tile the most populated cities within a dataset at zooms less than 7, then from zooms 8 through 16, only tile the top 20 most populated cities or towns per tile.
  • Only tile the top 5 flood-affected regions by area from the uploaded dataset until zoom 10, at zoom levels greater than 10, only show flooded regions with an area greater than 8 pixels.

Recipes must be constructed according to the rules in this recipe reference.

Recipe top-level fields

A recipe is a JSON object that must contain the following top-level fields:

Required fieldsDescriptionData type
version The version of the Mapbox Tiling Service recipe reference that the recipe uses. The current version number is 1. Any version value other than the current version or a previous version will result in an error.Integer
layers The LayerObject is an object in which the keys are the names of the layer and their values are objects that represent the configuration and options for the layer.Object
{
  "version": 1,
  "layers": { ... }
}

LayerObject

A layer object is the primary way of describing how a vector tile layer should be created. It specifies where to retrieve source data, the precision of the data through zoom levels, and how to transform features and render them into tiles. The following fields are the top-level options for a single layer:

Required fieldsDescriptionData type
source The source data to use for this layer. Tileset sources are created with the Create a tileset source endpoint of MTS.String
minzoom Describes the lowest zoom level for the tileset.Integer
maxzoom Describes the highest zoom level for the tileset. More info.Integer

You can further refine the resulting tileset with the following optional fields:

Optional fieldsDescriptionData type
features Specifies the output on a per feature basis. More info.Object
tiles Specifies the output on a per tile basis. More info.Object

The following describes every available field for a LayerObject and the JSON type that field must be. Fields with the Expression value indicates that those filters accept Mapbox expressions.

{
  "version": recipe_version,
  "layers": {
    ...: ...,
    layer: {
      "source": String,
      "minzoom": Number,
      "maxzoom": Number,
      "features": {
        "id": Expression,
        "attributes": {
          "zoom_element": [ ..., String ],
          "set": {
            ...: ...,
            attribute: Expression
          },
          "allowed_output": [ ..., String ]    (deprecated in favor of tiles field)
        },
        "filter": Expression<Boolean>,
        "simplification": Expression<Number>,
        "simplification": {
          "distance": Expression<Number>,
          "outward_only": Expression<Boolean>,
        },
        "bbox": [ Number, Number, Number, Number ],
      },
      "tiles": {
        "bbox": [ Number, Number, Number, Number ],
        "extent": Expression<Number>,
        "buffer_size": Expression<Number>
        "limit": [
          ...,
          [ String, Expression<Boolean>, Integer, String ],    (deprecated in favor of object)
          {
            "where": Expression<Boolean>,
            "sort_by": Expression,
            "sort_direction": String,
            "count": Number,
            "grid_scale": Number,
            "align_buffer_to_grid": Boolean
          }
        ],
        "union": [
          ...,
          {
            "where": Expression<Boolean>,
            "group_by": [ ..., String ]
            "aggregate": {
              ...: ...,
              attribute: String
            }
            "maintain_direction": Boolean,
            "grid_scale": Number,
            "cluster": Boolean,
            "simplification": Expression<Number>,
            "simplification": {
              "distance": Expression<Number>,
              "outward_only": Expression<Boolean>,
            }
          }
        ],
        "filter": Expression<Boolean>,
        "attributes": {
          "set": {
            ...: ...,
            attribute: Expression
          }
          "allowed_output": [ ..., String ]
        },
        "order": String,    (deprecated in favor of array of objects)
        "order": [
          ...,
          {
            "sort_by": Expression,
            "sort_direction": String
          }
        ],
        "remove_filled": Expression<Boolean>,
        "id": Expression,
        "layer_size": Number
      }
    }
  }
}

Basic example

The simplest example tileset recipe includes a layer name, a tileset source ID, a minimum zoom value, and a maximum zoom.

{
  "version": 1,
  "layers": {
    "trees": {
      "source": "mapbox://tileset-source/{username}/trees-data",
      "minzoom": 4,
      "maxzoom": 8
    }
  }
}

Multi-layer recipes

Recipes can also be arrays of recipe objects. This format can be used to create multi-layer tilesets. Recipes can have a maximum of 20 layers defined.

{
  "version": 1,
  "layers": {
    "trees": { ... },
    "parks": { ... },
    "paths": { ... }
  }
}

Layer name configuration

The layer name key is required for each LayerObject (e.g. "trees", "parks", and "paths" in the above example). This is the unique identifier for the layer of data in your final tileset. For any map each layer name must be unique. The layer name must be a string with only underscores (_) and alphanumeric characters.

Source configuration

A source refers to a tileset source, which is a collection of geographic data stored as line-delimited GeoJSON on Mapbox.com. Tileset sources can be created using MTS's Create a tileset source endpoint.

Zoom level configuration

The minzoom and maxzoom configurations control the zoom levels at which your data will be tiled. They are required for a recipe. These values must be integers. The minzoom must be less than or equal to maxzoom, and both must be between the values of 0 and 16.

Note

maxzoom does not determine which zoom level your maps zoom to. Your map will still zoom past the max zoom in your recipe because of overzooming.

The min and max zoom levels you choose directly impact the time it takes MTS to finish processing your data. Each additional zoom level increases the amount of data in the resulting tileset exponentially.

So, it’s important to first consider the use cases your map is trying to solve for when choosing your min and max zoom levels so that you don't incur any performance costs unnecessarily.

The following table will help you decide the appropriate minzoom and maxzoom based on your data precision:

Zoom levelPrecision in feetPrecision in metersUse CaseExample
032000 ft10000 m
116000 ft5000 m
28000 ft2500 m
34000 ft1250 m
42000 ft600 m
51000 ft300 m
6500 ft150 m
7250 ft80 m
8125 ft40 m
964 ft20 m
1032 ft10 mlow-resolution administrative boundaries (for example, countries and state boundaries)
1116 ft5 m
128 ft2 m
134 ft1 m
142 ft0.5 mhigh-resolution administrative boundaries (such as neighborhoods, census tracts, and towns), national park polygon data, national land use, and land cover polygon data
151 ft0.25 m
160.5 ft0.125 mbuilding/parcel polygon data, road polygon or line data, points of interest (such as hotels, restaurants, and venues)

Zoom levels greater than 16, which are applicable for use-cases like lane-level navigation maps or high-definition indoor maps, are not possible by default. If you have a use case that requires a zoom level greater than 16, reach out to us and let us know.

Feature configuration

The features configuration object is used to describe how features are individually processed into vector tiles. This field contains the following elements, which are evaluated in the order of the list provided below:

Optional fieldsDescriptionData type
id Gives you control over identifying and generating input features IDs. Read more about feature IDs and their customer operators in the "Identification" section. If you don't specify features.id, you get the GeoJSON feature ID. If the GeoJSON ID does not exist the ID will be a random integer using the random operator.Number or Array<Expression>
attributes A JSON object that controls how attributes are modified and which attributes are allowed in the resulting tileset.Object
filter A filter expression determining which features should be kept. If no filter is defined, the default filter is true and all features will be kept.Array
simplification An integer expression or value that is greater than zero that controls the level of simplification that occurs for features, or an object that specifies more detailed simplification control (see the "Feature simplification" section. This integer value is relative to the extent provided for the tiles, with a larger value resulting in more simplification.Integer or Expression or Object
bbox Clips each feature to the specified [minlon, minlat, maxlon, maxlatbounding box.Array<Number>

Feature filters

The filter configuration is a single filter expression that results in a true or false evaluation for each feature as configured by the minzoom and maxzoom. This is the primary way to control which features are allowed into the final tileset on a per-feature basis. If no filter is provided, by default this results in a value of true for all features.

Feature attributes

The attributes configuration allows for manipulation of attribute data, generation of new attributes, and removal of attributes. The available options are described below, and implemented in the order they are listed:

Optional fieldDescriptionData type
zoom_element A JSON array that provides a list of attributes that are specified per zoom level in the source data.Array<String>

For each attributes with a specified zoom_element, the final output attribute at zoom level N will be the Nth element in the array in the source data. If no zoom_element is defined, no attributes are altered. If the zoom level is greater than or equal to the number of elements in the array, the last element is used.

Consider the following attributes for a single GeoJSON feature:

{
  "type": "Feature",
  "geometry": { ... },
  "properties": { "name": [ null, null, "Main", "Main St.", "Main Street" ] }
}

In this example, the zoom_element array includes name. Using the attributes from the GeoJSON above, this feature would have no name attribute at zoom levels 0 and 1, would have "Main" at zoom level 2, "Main St." at zoom level 3, and "Main Street" at zoom levels 4 and above.

{
  "features": {
    "attributes": {
      "zoom_element": [ "name" ]
    }
  }
}
Optional fieldDescriptionData type
set A JSON object mapping the names of attributes to be generated to filter expressions that return the new attribute values. Particularly helpful for generating ranking schemes to be used in styling expressions.Object

Consider the following attributes for a single GeoJSON feature:

{
  "type": "Feature",
  "geometry": { ... },
  "properties": { "place": "state", "name": "California" }
}

In this example, the set attribute defines a new attribute to be included in the final tileset, labelrank, that is derived from the existing data's place attribute. Using the "match" expression, it assigns a value to features based on the value of "place". If "place" is equal to "country", then the labelrank attribute for the resulting feature will have a value of 0, and so on. It also provides a default value of 5 for any features that have a "place" value that does not match any of the values explicitly provided.

{
  "features": {
    "attributes": {
      "set": {
        "labelrank": [
          "match", [ "get", "place" ],
          "country", 0,
          "state", 1,
          "region", 2, "province", 2,
          "district", 3, "county", 3,
          "municipality", 4, "city", 4,
          5
        ]
      }
    }
  }
}
Optional fieldDescriptionData type
allowed_output A JSON array of attributes that controls which attributes will be carried over into the resulting tileset.Array<String>

If an allowed_output array is provided only the attributes specified in the array will be saved to the tileset. This does not prevent the attributes that are not excluded by allowed_output from being used in filter expressions and other steps throughout the publish job.

In this example, features in the resulting tileset will only have two attributes, name_en and name_es:

{
  "features": {
    "attributes": {
      "allowed_output": [ "name_en", "name_es" ]
    }
  }
}

Feature simplification

Optional fieldDescriptionData type
simplification Indicates the desired level of simplification. Larger values result in more simplification, in which some vertices are removed. The default value is 4. The maximum value is 4096.Integer or Expression or Object

The simplification expression or value describes the maximum distance that a point can be from the straight line that connects its two neighbors and still be considered to be on the line, and can be removed safely. Any point with a distance that is larger than the simplification value is considered to be away from the line, and must be preserved.

As you increase the simplification value, the number of vertices in each feature decreases. The MTS recipe validator will reject any simplification value that is more than 4096. If you do not add a value for simplification, MTS will use 4, the default value.

The resulting shape depends on the original shape of your feature. For instance, if your original feature is circular and you increase simplification, the result will look more like a polygon. If your original feature is a curved line and you increase simplification, the result will look more like a straight line.

MTS uses the Ramer–Douglas–Peucker algorithm to simplify features.

The simplification may be a constant number, or it may be an expression that evaluates to a number. A typical use for an expression for the simplification would be to use a minimal simplification at the layer's maximum zoom level, so it can be overzoomed with high precision, but to use a larger simplification at lower zoom levels that will never be magnified far.

If the simplification is an object, it can contain the following fields:

  • distance: An expression evaluating to the desired simplification level, as described above.
  • outward_only: An expression evaluating to true or false. If outward_only is true, then Polygon and MultiPolygon features will be simplified only in ways that slightly increase their area, never in ways that slightly decrease their area, so the borders of adjacent polygons will often overlap slightly instead of sometimes being separated by small gaps. This will increase the quality of polygon unioning if the recipe contains a union rule, at the cost of increased tile size because of reduced opportunity for simplification. (See the "Feature union" section.)

Note: Even if the simplification is specified as 0, complex features will receive additional simplification so that they can be rendered correctly by Mapbox GL. Polygons or MultiPolygons with more than 65535 vertices and LineStrings and polygon rings with more than 6553 points will be simplified to reduce their complexity to these limits.

Tile configurations

The tiles object contains the following elements, which are evaluated as each tile is being assembled from its component features:

Optional fieldDescriptionData type
buffer_size Controls the size of the buffer that will be created in your vector tiles. buffer_size is a percentage of the size of a tile. The default buffer size is 0.5. Note that the value of this attribute cannot be larger than 100. An expression can also be used in buffer_size, but must still return a number between 0 and 100. Buffers are particularly helpful for label point layers to avoid cutting labels of at tile boundaries.Number or Array<Expression>
bbox Clips each feature to the specified [minlon, minlat, maxlon, maxlatbounding box.Array<Number>
extent Controls the size of the extent of a vector tile. extent is a precision control for vector tiles, and by default is 4096. It is not recommended in most situations you change this value. If you set this value it must be a power of 2 between 256 and 8192. You may also set this number using an expression.Number or Array<Expression>
layer_size Specifies the size limit in kilobytes of each layer. The default value is 500 KiB. The value cannot be larger than 500 or smaller than 1. Configuring layer_size can be helpful for improving rendering speed.Integer
id Define the output ID encoded in your vector tiles. Read more about feature IDs and their customer operators in the "Identification" section. If this option is not defined, it will default to the resulting value of features.idNumber or Array<Expression>
remove_filled Control which "filled" features are removed by specifying a filter-expression.Array<Expression>

During tile creation it is possible for polygons to completely cover a tile and the area surrounding its buffer. These are called as "filled features". If all features within a tile are filled features, it may be useful for some tilesets to not create any tiles at all and expect that clients will look to higher zoom levels. To do this, you can use the remove_filled recipe.

The syntax utilizes a filter-expression to allow control over what features exactly should be removed.

"tiles": {
  "remove_filled": expression
}

No tile will be created if:

  • All features within the tile are considered filled features
  • All features are matched by the filter-expression provided in remove_filled

The following example removes all tiles that contain only filled features:

"tiles": {
  "remove_filled": true
}

The following example removes all tiles that contain only filled features after zoom level 5:

"tiles": {
  "remove_filled": [">", [ "zoom" ], 5]
}
Optional fieldDescriptionData type
limit A limitation rule that reduces the number of features for the specified type to a specific number, choosing the lowest or highest-numbered features according to some attribute.Array<Expression>

The limit field must be an array of limitation rules, each of which is evaluated in sequence to potentially limit the total number of features to be included in the final tile. There are two ways in which data is limited using the limit field, where and where_in_distance.

The where style limits the total number of features in the tile and its buffer. Only the first number of features that match a filter-expression are kept and the rest are dropped from the tile. The sorting of these is based on attribute which is the key to a feature's attribute and either sorted lowest to highest or highest to lowest.

The format for a where style limit are the following syntaxes:

  • [ "lowest_where", filter-expression , number , attribute ]
  • [ "highest_where", filter-expression , number , attribute ]

The where_in_distance is the second style of limit and subdivides a tile into number of regions. Within each region only one feature is kept from the features selected by the filter-expression for the limit. The number of regions contained within a single tile is controlled by region_count. This should always be a value equal to 4 to a power in size (e.g. 1, 4, 16, 64, 256..), if the region_count is not equal to one of these numbers it will be rounded to the nearest value of one of these numbers in processing. The feature that is selected in a region is based on either the highest or lowest value based on the attribute field.

The format for a where_in_distance style limit are the following syntaxes:

  • [ "lowest_where_in_distance", filter-expression , region_count , attribute ]
  • [ "highest_where_in_distance", filter-expression , region_count , attribute ]
Optional fieldDescriptionData type
order Specify the order of a sequence of features in the final output tile. The features with the lowest values are placed in the tile first.String

You can order the sequence of features in the final output tile by a specified attribute. The attribute values must be comparable (all strings or all numbers).

This example orders the features by the sequence attribute:

"tiles": { "order": "sequence" }

Renderers, including Mapbox GL, draw or place features in the order they appear in the tile. LineString and Polygon features that are drawn early in the sequence may be covered by overlapping features that are drawn later in the sequence. Conversely, labels that are placed early in the sequence will prevent labels of features later in the sequence from being placed nearby.

You can follow these general guidelines:

  • The most important LineStrings and Polygons should have the highest values for their order attribute, so they are not covered by overlapping features.
  • The most important labels should have the lowest values for their order attribute, so they are placed first.

Read more about how label visibility is affected by the order of features in the Optimize map label placement guide.

If no order attribute is specified, the features will appear in an unpredictable order.

Feature union

Optional fieldDescriptionData type
union Join features based on whether or not a defined specified attribute matches.Object

You can union features together if a specified set of their attributes match. The simplest case unions all features that have exactly the same attributes:

"tiles": { "union": [ { } ] }

The union specification object can contain an expression to union only features that match the specified expression as well as having matching attributes:

"where": expression

Additional union options:

  • group_by: [attribute, attribute, attribute] - Use group_by to union features that have specified attributes that match, instead of requiring all attributes to match.
  • aggregate: { attribute: type, attribute: type } - Use aggregate to accumulate the specified attributes from the unioned features. Attributes that are not specified in either group_by or aggregate will be removed. Acceptable types of aggregation include sum (to add numbers), product (to multiply numbers), min (to choose the lowest number), max (to choose the highest number), mean (to take the average of numbers), comma (to concatenate with a comma), concat (to concatenate the feature data without a delimiter), arbitrary (to take the attribute from one of the source features), or arbitrary-non-null (to take the attribute from one of the source features where the attribute is not null).
  • maintain_direction: boolean - Use maintain_direction: false to make more compact unions of LineStrings for which directionality doesn't matter. This reverses some of the LineStrings if that helps to connect them.
  • simplification: expression or object - Specifies how features will be resimplified after unioning, as described in the Feature simplification section. For polygon unions, it is often useful to specify outward_only: true in the main simplification section, so the source features will slightly overlap and be merged into a single geometry. Then you can specify outward_only: false in the union's post-unioning simplification section, so additional simplification will be applied to the polygon after unioning has already taken their overlap into account.

For example, you could specify the following to union only features where highway=motorway, and keep the average of their speed_limit attributes:

"tiles": {
  "union":
  [
    {
      "where": [ "==", [ "get", "highway" ], "motorway" ],
      "maintain_direction": true,
      "aggregate": { "speed_limit": "mean" }
    }
  ]
}

This example uses maintain_direction: true (the default) because motorway roads are generally mapped as pairs of roadways whose direction indicates their one-way direction.

For a more elaborate union example, see the Census Blocks example in the Tilesets recipe examples

Using union with zoom based properties

You can use union on zoom-element properties. If you are using union with a zoom-element property, the union will occur after the feature has been assigned the value based on the zoom level.

Identification

You can configure the identification of features in both "Features" and "Tiles". Both follow the same patterns and have the same options. In general, features.id is used for defining or generating input IDs, while tiles.id is used for defining or generating output IDs in the final vector tiles.

{
  "features": {
    "id": [ <Expression> ]
  },
  "tiles": {
    "id": [ <Expression> ]
  }
}

All IDs encoded in the final vector tiles will be integers, as defined by the vector tile specification. If you provide a string value to tiles.id the value will be automatically hashed to an integer between 0 and 2^53.

Order of operations

The following describes the order of operations and type conversions applied when using the features.id and tiles.id options. Remember the Mapbox Vector Tile specification requires all IDs to be encoded as positive integers between 0 and 2^53.

  • In general ID value in either features.id or tiles.id will be converted to an Integer or Float if possible and will otherwise return a string or Null value.
  • If features.id is not defined, the top-level id of the GeoJSON feature will be used.

    • If there is no top-level id from the GeoJSON feature, a random integer will be generated.
    • If the value is set to null, no feature ID is set.
  • If features.id is defined, the result of the expression will be converted to an Integer or Float if possible and will otherwise return a string.

    • If the expression returns a null value, a random integer will be generated. If you are trying to prevent feature IDs in your final tile, set tiles.id to null.
  • If tiles.id is not defined, the resulting value from features.id will be used.
  • If tiles.id is defined, the value of the resulting expression replaces whatever value was defined in features.id.
  • If the result of the tiles.id expression is a...

    • string, it is hashed to an integer.
    • string representation of a number, it will be converted to the absolute value of that number truncated to an integer, modulo 2^53.
    • empty string, it will be treated as null and not encoded.
    • negative number, the absolute value will be used.
    • floating point number, it will be rounded and fit within 0 to 2^53.
    • boolean, it will be treated as null and not encoded.

If you don't want to encode any IDs in your final vector tile you can pass null to tiles.id as your value instead of an expression array.

Duplicate IDs

While ID collision for unidentified features is unlikely, unique IDs aren't guaranteed since feature parsing occurs in a distributed environment. To guarantee unique identifiers, bring your own IDs. Duplicate feature IDs can cause unexpected behavior in tilesets and should be avoided.

Expressions reference

Instead of applying a recipe option across your entire layer, some recipe options allow you to filter your source data on a per feature, per tile, or per zoom level basis. These filtering capabilities are possible with Mapbox expressions.

An expression defines a formula for computing the value of a property using the operators described below. The set of expression operators provided by MTS includes:

  • Mathematical operators for performing arithmetic and other operations on numeric values
  • Logical operators for manipulating boolean values and making conditional decisions
  • String operators for manipulating strings
  • Data operators that provide access to the properties of features in your tileset source

Expressions are represented as JSON arrays. The first element of an expression array is a string naming the expression operator, for example "*" or "case". Elements that follow (if any) are the arguments to the expression. Each argument is either a literal value (a string, number, boolean, or null), or another expression array.

[expression_name, argument_0, argument_1, ...]

Expressions allow you to dynamically filter source data to optimize your output tileset. The LayerObject houses all the available recipe options and denotes which fields accept expressions by listing a Expression value.

Data expressions

A data expression is any expression that accesses data in your tileset source — that is, any expression that uses one of the data operators: get, has, id, geometry-type, or properties. Data expressions allow a feature's properties to determine its appearance. They can be used to differentiate features within the same layer and to create data visualizations.

{
  "version": 1,
  "layers": {
    "roads": {
      "source": "mapbox://tileset-source/{username}/building-data",
      "minzoom": 0,
      "maxzoom": 5,
      "features": {
        "attributes": {
          "set": {
            "building_age": ['-', 2020, ['number', ['get', 'construction_completion_date'], 2020]]
          }
        }
      }
    }
  }
}

This example uses the get operator to get the construction_completion_date value of each feature. That value is then used to calculate the building_age, by using the math operator - to subtract the current year, 2020, from the construction_completion_date. Finally, we use the set operator to set a building_age property on each feature, which contains the age of the building.

Types

The expressions in this section are for testing for and converting between different data types like strings, numbers, and boolean values.

Often, such tests and conversions are unnecessary, but they are helpful if a feature's data type is ambiguous or inconsistent. They can also be useful in cases where your feature data has inconsistent types; for example, you could use to-number to make sure that values like "1.5" (instead of 1.5) are treated as numeric values.

In the example below, we use the operation to-number to set the type value of construction-date from a string to a numeric value. If a value does not exist, it returns the default value: 2020.

{
  "version": 1,
  "layers": {
    "roads": {
      "source": "mapbox://tileset-source/{username}/building-data",
      "minzoom": 0,
      "maxzoom": 5,
      "features": {
        "attributes": {
          "set": {
            "building_age": ['-', 2020, ['to-number', ['get', construction-date], 2020]]
          }
        }
      }
    }
  }
}

array

Asserts that the input is an array (optionally with a specific item type and length). If, when the input expression is evaluated, it is not of the asserted type, then this assertion will cause the whole expression to be aborted.

["array", value]: array
["array", type: "string" | "number" | "boolean", value]: array<type>
["array",
    type: "string" | "number" | "boolean",
    N: number (literal),
    value
]: array<type, N>

boolean

Asserts that the input value is a boolean. If multiple values are provided, each one is evaluated in order until a boolean is obtained. If none of the inputs are booleans, the expression is an error.

["boolean", value]: boolean
["boolean", value, fallback: value, fallback: value, ...]: boolean

literal

Provides a literal array or object value.

["literal", [...] (JSON array literal)]: array<T, N>
["literal", {...} (JSON object literal)]: object

number

Asserts that the input value is a number. If multiple values are provided, each one is evaluated in order until a number is obtained. If none of the inputs are numbers, the expression is an error.

["number", value]: number
["number", value, fallback: value, fallback: value, ...]: number

number-format

Converts the input number into a string representation using the providing formatting rules. If set, the locale argument specifies the locale to use, as a BCP 47 language tag. If set, the currency argument specifies an ISO 4217 code to use for currency-style formatting. If set, the min-fraction-digits and max-fraction-digits arguments specify the minimum and maximum number of fractional digits to include.

["number-format",
    input: number,
    options: { "locale": string, "currency": string, "min-fraction-digits": number, "max-fraction-digits": number }
]: string

object

Asserts that the input value is an object. If multiple values are provided, each one is evaluated in order until an object is obtained. If none of the inputs are objects, the expression is an error.

["object", value]: object
["object", value, fallback: value, fallback: value, ...]: object

string

Asserts that the input value is a string. If multiple values are provided, each one is evaluated in order until a string is obtained. If none of the inputs are strings, the expression is an error.

["string", value]: string
["string", value, fallback: value, fallback: value, ...]: string

to-boolean

Converts the input value to a boolean. The result is false when then input is an empty string, 0, false, null, or NaN; otherwise it is true.

["to-boolean", value]: boolean

to-number

Converts the input value to a number, if possible. If the input is null or false, the result is 0. If the input is true, the result is 1. If the input is a string, it is converted to a number as specified by the "ToNumber Applied to the String Type" algorithm of the ECMAScript Language Specification. If multiple values are provided, each one is evaluated in order until the first successful conversion is obtained. If none of the inputs can be converted, the expression is an error.

["to-number", value, fallback: value, fallback: value, ...]: number

to-string

Converts the input value to a string. If the input is null, the result is "". If the input is a boolean, the result is "true" or "false". If the input is a number, it is converted to a string as specified by the "NumberToString" algorithm of the ECMAScript Language Specification. If the input is a color, it is converted to a string of the form "rgba(r,g,b,a)", where r, g, and b are numerals ranging from 0 to 255, and a ranges from 0 to 1. Otherwise, the input is converted to a string in the format specified by the JSON.stringify function of the ECMAScript Language Specification.

["to-string", value]: string

typeof

Returns a string describing the type of the given value.

["typeof", value]: string

Feature data

The expressions in this section (geometry-type, properties, and id) are for retrieving information about the attributes contained in the GeoJSON specification.

The example below uses the id operation to set an ID from an attribute instead of the top-level id field of the feature. In this case, company_integer_id is the field used for the id of each feature.

{
  "version": 1,
  "layers": {
    "countries": {
      "source": "mapbox://tileset-source/{username}/feature-ids",
      "minzoom": 7,
      "maxzoom": 7,
      "features": {
        "id": [ "get", "company_integer_id" ]
      }
    }
  }
}

feature

Provides a static, integer representation of the feature. The hash is generated from the geometry, geometry type, and properties sorted alphabetically. If this option is used in the tiles.id section, it is only the part of the feature within the individual tile, not the entire original feature.

["feature"]: number

geometry-type

Gets the feature's geometry type: Point, MultiPoint, LineString, MultiLineString, Polygon, MultiPolygon.

["geometry-type"]: string

id

Gets the feature's ID, if it has one.

["id"]: value

properties

Gets the feature properties object. Note that in some cases, it may be more efficient to use ["get", "property_name"] directly.

["properties"]: object

Lookup

The expressions in this section are for retrieving information about feature properties contained in the GeoJSON specification.

The example below uses the operation get to retrieve the construction date, subtract the date from the current year, and then set a building_age property on each feature. 2020 is set as the default if construction-date is missing or invalid.

{
  "version": 1,
  "layers": {
    "roads": {
      "source": "mapbox://tileset-source/{username}/building-data",
      "minzoom": 0,
      "maxzoom": 5,
      "features": {
        "attributes": {
          "set": {
            "building_age": ['-', 2020, ['number', ['get', construction-date], 2020]]
          }
        }
      }
    }
  }
}

at

Retrieves an item from an array.

["at", number, array]: ItemType

get

Retrieves a property value from the current feature's properties, or from another object if a second argument is provided. Returns null if the requested property is missing.

["get", string]: value
["get", string, object]: value

has

Tests for the presence of an property value in the current feature's properties, or from another object if a second argument is provided.

["has", string]: boolean
["has", string, object]: boolean

in

Determines whether an item exists in an array or a substring exists in a string.

["in",
    keyword: InputType (boolean, string, or number),
    input: InputType (array or string)
]: boolean

index-of

Returns the first position at which an item can be found in an array or a substring can be found in a string, or -1 if the input cannot be found. Accepts an optional index from where to begin the search.

["index-of",
    keyword: InputType (boolean, string, or number),
    input: InputType (array or string)
]: number
["index-of",
    keyword: InputType (boolean, string, or number),
    input: InputType (array or string),
    index: number
]: number

length

Gets the length of an array or string.

["length", string | array | value]: number

slice

Returns an item from an array or a substring from a string from a specified start index, or between a start index and an end index if set. The return value is inclusive of the start index but not of the end index.

["slice",
    input: InputType (array or string),
    index: number
]: OutputType (ItemType or string)
["slice",
    input: InputType (array or string),
    index: number,
    index: number
]: OutputType (ItemType or string)

Decision

The expressions in this section can be used to add conditional logic to your styles. For example, the 'case' expression provides "if/then/else" logic, and 'match' allows you to map specific values of an input expression to different output expressions.

The example below uses the match operation to include any features that contain the highway property with a value of secondary or motorway at zoom 6 or higher.

{
  "version": 1,
  "layers": {
    "road_network": {
      "source": "mapbox://tileset-source/username/roads",
      "minzoom": 0,
      "maxzoom": 14,
      "features": {
        "filter": [
          "any",
          [
            "all",
            [ ">=", [ "zoom" ], 6 ],
            [ "match", [ "get", "highway" ],
              "secondary", true, "motorway", true, false ]
          ]
        ]
      }
    }
  }
}

!

Logical negation. Returns true if the input is false, and false if the input is true.

["!", boolean]: boolean

!=

Returns true if the input values are not equal, false otherwise. The comparison is strictly typed: values of different runtime types are always considered unequal. Cases where the types are known to be different at parse time are considered invalid and will produce a parse error. Accepts an optional collator argument to control locale-dependent string comparisons.

["!=", value, value]: boolean
["!=", value, value, collator]: boolean

<

Returns true if the first input is strictly less than the second, false otherwise. The arguments are required to be either both strings or both numbers; if during evaluation they are not, expression evaluation produces an error. Cases where this constraint is known not to hold at parse time are considered in valid and will produce a parse error. Accepts an optional collator argument to control locale-dependent string comparisons.

["<", value, value]: boolean
["<", value, value, collator]: boolean

<=

Returns true if the first input is less than or equal to the second, false otherwise. The arguments are required to be either both strings or both numbers; if during evaluation they are not, expression evaluation produces an error. Cases where this constraint is known not to hold at parse time are considered in valid and will produce a parse error. Accepts an optional collator argument to control locale-dependent string comparisons.

["<=", value, value]: boolean
["<=", value, value, collator]: boolean

==

Returns true if the input values are equal, false otherwise. The comparison is strictly typed: values of different runtime types are always considered unequal. Cases where the types are known to be different at parse time are considered invalid and will produce a parse error. Accepts an optional collator argument to control locale-dependent string comparisons.

["==", value, value]: boolean
["==", value, value, collator]: boolean

>

Returns true if the first input is strictly greater than the second, false otherwise. The arguments are required to be either both strings or both numbers; if during evaluation they are not, expression evaluation produces an error. Cases where this constraint is known not to hold at parse time are considered in valid and will produce a parse error. Accepts an optional collator argument to control locale-dependent string comparisons.

[">", value, value]: boolean
[">", value, value, collator]: boolean

>=

Returns true if the first input is greater than or equal to the second, false otherwise. The arguments are required to be either both strings or both numbers; if during evaluation they are not, expression evaluation produces an error. Cases where this constraint is known not to hold at parse time are considered in valid and will produce a parse error. Accepts an optional collator argument to control locale-dependent string comparisons.

[">=", value, value]: boolean
[">=", value, value, collator]: boolean

all

Returns true if all the inputs are true, false otherwise. The inputs are evaluated in order, and evaluation is short-circuiting: once an input expression evaluates to false, the result is false and no further input expressions are evaluated.

["all", boolean, boolean]: boolean
["all", boolean, boolean, ...]: boolean

any

Returns true if any of the inputs are true, false otherwise. The inputs are evaluated in order, and evaluation is short-circuiting: once an input expression evaluates to true, the result is true and no further input expressions are evaluated.

["any", boolean, boolean]: boolean
["any", boolean, boolean, ...]: boolean

case

Selects the first output whose corresponding test condition evaluates to true, or the fallback value otherwise.

["case",
    condition: boolean, output: OutputType,
    condition: boolean, output: OutputType,
    ...,
    fallback: OutputType
]: OutputType

coalesce

Evaluates each expression in turn until the first non-null value is obtained, and returns that value.

["coalesce", OutputType, OutputType, ...]: OutputType

match

Selects the output whose label value matches the input value, or the fallback value if no match is found. The input can be any expression (e.g. ["get", "building_type"]). Each label must be either:

  • a single literal value; or
  • an array of literal values, whose values must be all strings or all numbers (e.g. [100, 101] or ["c", "b"]). The input matches if any of the values in the array matches, similar to the "in" operator. Each label must be unique. If the input type does not match the type of the labels, the result will be the fallback value.
["match",
    input: InputType (number or string),
    label: InputType | [InputType, InputType, ...], output: OutputType,
    label: InputType | [InputType, InputType, ...], output: OutputType,
    ...,
    fallback: OutputType
]: OutputType

within

Returns true if the evaluated feature is fully contained inside a boundary of the input geometry, false otherwise. The input value can be a valid GeoJSON of type Polygon, MultiPolygon, Feature, or FeatureCollection. Supported features for evaluation:

  • Point: Returns false if a point is on the boundary or falls outside the boundary.
  • LineString: Returns false if any part of a line falls outside the boundary, the line intersects the boundary, or a line's endpoint is on the boundary.
["within", object]: boolean

Scales

The expression in this section provides incremental filters using the step operation. The example below uses step to set simplification at each zoom level. The default value is 10, and then the each step value indicates the simplification to be applied within a zoom range.

  • Zoom 0 - 2 has a simplification value of 10 because that is the default value.
  • Zoom 3 - 6 has a simplification value of 2.
  • Zoom 7 - 9 has a simplification value of 1.
  • Zoom 10+ has a simplification value of 0. These zoom-based step values result in features that are more precise as you zoom in.
{
  "version": 1,
  "layers": {
    "roads": {
      "source": "mapbox://tileset-source/{username}/building-data",
      "minzoom": 3,
      "maxzoom": 12,
      "features": {
             "simplification": [
               "step",
               ["zoom"],
               10,
               3,
               2,
               7,
               1,
             10,
             0
             ]
      }
    }
  }
}

step

Produces discrete, stepped results by evaluating a piecewise-constant function defined by pairs of input and output values ("stops"). The input may be any numeric expression (e.g., ["get", "population"]). Stop inputs must be numeric literals in strictly ascending order. Returns the output value of the stop just less than the input, or the first output if the input is less than the first stop.

["step",
    input: number,
    stop_output_0: OutputType,
    stop_input_1: number, stop_output_1: OutputType,
    stop_input_n: number, stop_output_n: OutputType, ...
]: OutputType

Variable binding

The expressions in this section are for binding variables. In most cases, recipes will use the set recipe field to create a new feature property, but var and let allow performing and referring to partial calculations within a single expression. This may be necessary instead of referring to another set attribute, because the order that set operations will take place in is not defined.

let

Binds expressions to named variables, which can then be referenced in the result expression using ["var", "variable_name"].

["let",
    string (alphanumeric literal), any, string (alphanumeric literal), any, ...,
    OutputType
]: OutputType

var

References variable bound using "let".

["var", previously bound variable name]: the type of the bound expression

String

The expressions in this section are for manipulating string values.

The example below uses the string concat operation to combine the string construction-date value with the description value of each feature. The building_description of each property is then set to this string value.

{
  "version": 1,
  "layers": {
    "roads": {
      "source": "mapbox://tileset-source/{username}/building-data",
      "minzoom": 0,
      "maxzoom": 5,
      "features": {
        "attributes": {
          "set": {
            "building_description": ['concat', ['get', `construction-date`],2020], ":", ['get', ‘description’], ‘no description provided’]]
          }
        }
      }
    }
  }
}

concat

Returns a string consisting of the concatenation of the inputs. Each input is converted to a string as if by to-string.

["concat", value, value, ...]: string

downcase

Returns the input string converted to lowercase. Follows the Unicode Default Case Conversion algorithm and the locale-insensitive case mappings in the Unicode Character Database.

["downcase", string]: string

is-supported-script

Returns true if the input string is expected to render legibly. Returns false if the input string contains sections that cannot be rendered without potential loss of meaning (e.g. Indic scripts that require complex text shaping, or right-to-left scripts if the the mapbox-gl-rtl-text plugin is not in use in Mapbox GL JS).

["is-supported-script", string]: boolean

resolved-locale

Returns the IETF language tag of the locale being used by the provided collator. This can be used to determine the default system locale, or to determine if a requested locale was successfully loaded.

["resolved-locale", collator]: string

upcase

Returns the input string converted to uppercase. Follows the Unicode Default Case Conversion algorithm and the locale-insensitive case mappings in the Unicode Character Database.

["upcase", string]: string

Math

The expressions in this section are for applying mathematical operations.

In the example below, we retrieve the construction date, use the Math operation - to subtract the date from the current year, and then set a building_age property on each feature. We set 2020 as the default if the construction-date is missing.

{
  "version": 1,
  "layers": {
    "roads": {
      "source": "mapbox://tileset-source/{username}/building-data",
      "minzoom": 0,
      "maxzoom": 5,
      "features": {
        "attributes": {
          "set": {
            "building_age": ['-', 2020, ['number', ['get', construction-date], 2020]]
          }
        }
      }
    }
  }
}

-

For two inputs, returns the result of subtracting the second input from the first. For a single input, returns the result of subtracting it from 0.

["-", number, number]: number
["-", number]: number

*

Returns the product of the inputs.

["*", number, number, ...]: number

/

Returns the result of floating point division of the first input by the second.

["/", number, number]: number

%

Returns the remainder after integer division of the first input by the second.

["%", number, number]: number

^

Returns the result of raising the first input to the power specified by the second.

["^", number, number]: number

+

Returns the sum of the inputs.

["+", number, number, ...]: number

abs

Returns the absolute value of the input.

["abs", number]: number

acos

Returns the arccosine of the input.

["acos", number]: number

asin

Returns the arcsine of the input.

["asin", number]: number

atan

Returns the arctangent of the input.

["atan", number]: number

ceil

Returns the smallest integer that is greater than or equal to the input.

["ceil", number]: number

cos

Returns the cosine of the input.

["cos", number]: number

distance

Returns the shortest distance in meters between the evaluated feature and the input geometry. The input value can be a valid GeoJSON of type Point, MultiPoint, LineString, MultiLineString, Polygon, MultiPolygon, Feature, or FeatureCollection. Distance values returned may vary in precision due to loss in precision from encoding geometries, particularly below zoom level 13.

["distance", object]: number

e

Returns the mathematical constant e.

["e"]: number

floor

Returns the largest integer that is less than or equal to the input.

["floor", number]: number

hash

Generates a unique integer from a string value. Particularly helpful for generating IDs from a combination of the feature attributes.

["hash", string]: number

ln

Returns the natural logarithm of the input.

["ln", number]: number

ln2

Returns mathematical constant ln(2).

["ln2"]: number

log10

Returns the base-ten logarithm of the input.

["log10", number]: number

log2

Returns the base-two logarithm of the input.

["log2", number]: number

max

Returns the maximum value of the inputs.

["max", number, number, ...]: number

min

Returns the minimum value of the inputs.

["min", number, number, ...]: number

pi

Returns the mathematical constant pi.

["pi"]: number

random

Generates a random integer between 0 and 2^53. This operator is used by default for any features that do not have an ID defined.

["random"]: number

round

Rounds the input to the nearest integer. Halfway values are rounded away from zero. For example, ["round", -1.5] evaluates to -2.

["round", number]: number

sin

Returns the sine of the input.

["sin", number]: number

sqrt

Returns the square root of the input.

["sqrt", number]: number

tan

Returns the tangent of the input.

["tan", number]: number

Zoom

The expressions in this section are for applying zoom specific filtering to your data.

In the example below, we use the zoom operation to only apply the match filters to data at zoom 6 or higher.

{
  "version": 1,
  "layers": {
    "road_network": {
      "source": "mapbox://tileset-source/username/roads",
      "minzoom": 0,
      "maxzoom": 14,
      "features": {
        "filter": [
          "any",
          [
            "all",
            [ ">=", [ "zoom" ], 6 ],
            [ "match", [ "get", "highway" ],
              "secondary", true, "motorway", true, false ]
          ]
        ]
      }
    }
  }
}

zoom

Gets the current zoom level. Note that in style layout and paint properties, ["zoom"] may only appear as the input to a top-level "step" or "interpolate" expression.

["zoom"]: number

More resources

Was this page helpful?