Query a source
A source query reports the loaded features in a source, including features that no layer draws. To find features at a screen position, use Query a map.
The query belongs to the render session and runs on the session’s owner thread. Source queries become available after the first render update. An earlier query reports an invalid-state status.
Run the query
Section titled “Run the query”A vector source needs source-layer IDs, because one vector tile holds several layers and MapLibre reads the layers that you name. A vector query with no source-layer ID returns zero features. A GeoJSON source holds a single layer and ignores the field.
const mln_buffer_view source_layers[] = {view("poi")};mln_source_feature_query_options options = mln_source_feature_query_options_default();options.fields = MLN_SOURCE_FEATURE_QUERY_OPTION_SOURCE_LAYER_IDS;options.source_layer_ids = source_layers;options.source_layer_id_count = 1;Name the source itself by its style source ID. That ID is the query’s second argument, and it differs from the source-layer IDs in the options.
mln_queried_feature_list result = MLN_HANDLE_NULL;const mln_status queried = mln_render_session_query_source_features( session, view("places"), &options, &result);if (queried != MLN_STATUS_OK) return;
read_features(result);mln_queried_feature_list_destroy(result);A successful query can return no hits for an unknown source ID. Copy every value that the host keeps.
size_t count = 0;if (mln_queried_feature_list_count(result, &count) != MLN_STATUS_OK) return;if (count == 0) return;mln_queried_feature hit = mln_queried_feature_default();if (mln_queried_feature_list_get(result, 0, &hit) != MLN_STATUS_OK) return;// Copy hit.feature and any identifier or state view you keep.A query covers the tiles that the source loaded for the current camera. Its result therefore changes as the camera moves and more tiles arrive. A source loads tiles only while a layer uses it.
Expand a cluster
Section titled “Expand a cluster”An extension query runs a named extension against one source feature. The
supercluster extension reads a clustered GeoJSON source. Its leaves field
returns the features under one cluster as a feature collection.
supercluster matches numbers by exact native JSON type. Encode limit and
offset as nonnegative integer literals so MapLibre reads them as unsigned
values.
const mln_buffer_view arguments = view("{\"limit\":10,\"offset\":0}");The call names the source, the cluster feature, the extension, and the field within that extension.
mln_buffer result = MLN_HANDLE_NULL;const mln_status queried = mln_render_session_query_feature_extensions( session, view("places"), cluster, view("supercluster"), view("leaves"), &arguments, &result);if (queried == MLN_STATUS_OK) read_leaves(result);
mln_buffer_destroy(result);An extension result is one owned buffer. For leaves, parse it as a
GeoJSON FeatureCollection; scalar extension fields return their JSON value.
mln_buffer_view json = {0};if (mln_buffer_get(result, &json) != MLN_STATUS_OK) return;// Parse json.data[0..json.size] as a GeoJSON FeatureCollection. Each feature// is one point that the cluster contains.Pass the Feature bytes from a queried feature to the extension query.
supercluster also matches cluster_id by exact JSON type. Preserve its
nonnegative integer literal; rewriting every number as a double produces a
successful query with an empty result.