Locate Search
This guide explains how to configure locate-search.xml for business needs: what each field means, allowed values, and which setup to choose for common use cases.
What You Configure
You configure one or more providers in locate-search.xml.
Each provider is one searchable source (for example: addresses, parcels, water assets, organizational units).
At runtime, the system queries all configured providers and merges the results.
1) Provider Blueprint
Use this as the base shape for each provider:
<ber:locateSearchProvider
id="your_provider_id"
type="rest"
providerType="geojson|lidsElastic"
name="Visible provider name"
order="1"
defaultColor="#00FF00"
defaultIcon="info"
coordinatesOrder="xy|yx">
<ber:locateSearchCategoryArray>
<ber:locateSearchCategory id="category_id" name="Category label" color="#ABCDEF" icon="ic_example"/>
</ber:locateSearchCategoryArray>
<ber:commonRestInputConfiguration method="GET|POST" removeBlanks="true|false">
<ber:url>...</ber:url>
<ber:requestBody>...</ber:requestBody>
<ber:replaceBlanks>+</ber:replaceBlanks>
</ber:commonRestInputConfiguration>
<ber:categorySource type="property" name="origin"/>
<ber:responseForm>
<ber:name>label</ber:name>
</ber:responseForm>
</ber:locateSearchProvider>
2) Field Reference (Allowed Values + Meaning)
A. Provider-level fields
| Field | Required | Allowed values | Business meaning |
|---|---|---|---|
id | yes | any unique text (e.g. swtopo_address, lids_water) | Internal unique key of the provider |
type | yes | rest | Keep fixed to rest |
providerType | yes | geojson, lidsElastic | Source type: external GeoJSON API vs LIDS Elasticsearch |
name | yes | any text | Provider label users see in results |
order | yes | integer (1, 2, 3, ...) | Display priority (lower number = higher priority) |
defaultColor | no | hex color (e.g. #00FF00) | Fallback color when category has no color |
defaultIcon | no | icon key used in your client setup | Fallback icon when category has no icon |
coordinatesOrder | no | xy or yx | Coordinate interpretation for GeoJSON geometry; use yx for many external map APIs |
B. Category mapping fields
| Field | Required | Allowed values | Business meaning |
|---|---|---|---|
locateSearchCategory[@id] | yes | source category key (e.g. district, ft_5010100) | Category identifier coming from search source |
locateSearchCategory[@name] | no | any text | User-friendly category label |
locateSearchCategory[@color] | no | hex color | Category-specific color |
locateSearchCategory[@icon] | no | icon key | Category-specific icon |
C. Request fields (commonRestInputConfiguration)
| Field | Required | Allowed values | Business meaning |
|---|---|---|---|
method | yes | GET, POST | How to call the source |
url | yes | URL/path text | Endpoint to call. Use %%SEARCH_PHRASE%% placeholder for user input |
requestBody | POST scenarios | JSON text | Body for POST search requests |
removeBlanks | no | true, false | If true, spaces are removed from search text |
replaceBlanks | no | any replacement string (+, %20, etc.) | Replace spaces with a specific character/string |
Important rule: do not use both removeBlanks="true" and <ber:replaceBlanks>...</ber:replaceBlanks> in the same provider.
D. Additional fields
| Field | Required | Allowed values | Business meaning |
|---|---|---|---|
categorySource[@type] | for geojson | property | Category comes from a property in response |
categorySource[@name] | for geojson | property key (e.g. origin) | Which property contains category id |
responseForm/name | recommended | property/field name (label, featureInfo, etc.) | Which field is shown as main result text |
3) Which Provider Type Should You Use?
Choose providerType="geojson" when:
- You search data from an external API returning GeoJSON.
- You can pass user text in URL query parameters.
- Categories are provided in response properties (e.g.
origin).
Typical examples: addresses, districts, municipalities, parcels from public map APIs.
Choose providerType="lidsElastic" when:
- You search internal LIDS business data indexed in Elasticsearch.
- You need structured POST JSON query (types, query, size, optional geometries).
- Category is based on your internal feature types (e.g.
ft_5010100).
Typical examples: utility assets, internal parcel layers, organization-specific entities.
4) lidsElastic requestBody Reference
The requestBody is a JSON object passed directly to /rest/search/features. All fields:
{
"types": ["ft_5010100", "ft_5012100", "ft_parcel_area"],
"query": { ... },
"size": 20,
"from": 0,
"geometries": ["ft_parcel_face"],
"typeQuery": { "ft_5010100": { ... } },
"interfaceQuery": { "<key>": { ... } },
"interfaceOperator": "AND",
"relationsFilter": { "<relatedType>": ["<relatedFeatureId>"] },
"typeRelationsFilter": { "<searchedType>": { "<relatedType>": ["<relatedId>"] } }
}
| Field | Required | Description |
|---|---|---|
types | yes | Feature type IDs to search. Only semantic parent types for shared semantics (see sharedSemantics below). |
query | yes | Query condition applied across all types. Use %%SEARCH_PHRASE%% as placeholder. |
size | no | Max results to return (default: 10). |
from | no | Offset for pagination. Note: totalHits is capped to from + size. |
geometries | no | Filter returned geometries for shared semantics by feature type ID, e.g. ["ft_parcel_face"]. Omit to return all geometry types. |
typeQuery | no | Per-feature-type query condition (key = feature type ID). Combined with query via AND. |
interfaceQuery | no | Cross-type condition using interface attributes (key = arbitrary string). |
interfaceOperator | no | "AND" (default) or "OR" — how typeQuery / interfaceQuery combine. |
relationsFilter | no | Filter by related features across all types. |
typeRelationsFilter | no | Per-type relation filter. |
Query condition types
Every query condition has at least a type field. Use %%SEARCH_PHRASE%% for user input:
type | Additional fields | Notes |
|---|---|---|
matchPhrasePrefix | field, value, operator | Recommended for locate-search. Prefix-matches user input on text fields. "field": "all" searches all indexed text attributes at once. |
wildcard | field, query | Pattern with * / ?. Use .keyword suffix on the field name (e.g. "at_5120002.keyword"). %%SEARCH_PHRASE%%* is a typical pattern. |
match | field, query, operator | Full-text match. Operator: "and" or "or". |
matchPhrase | field, query | Exact phrase match. |
matchAll | — | Matches all indexed documents. |
terms | field, values | Exact match against a list of values. Use .keyword suffix. |
range | field, from, to, includeUpper, includeLower | Numeric or date range. |
exists | field | Matches documents where the field is present. |
bool | must, should, must_not | Compound query. Each is a list of nested conditions. |
disMax | queries | Disjunction-max across a list of sub-queries (highest-scoring clause wins). |
geoShape | field, shapeType, shapeCoordinates, relation, srs | Spatial filter against the geometry stored in Elasticsearch. relation: intersects, within, contains, disjoint. |
The special "field": "all" value searches across all indexed text attributes simultaneously — it is the most common choice for locate-search.
Examples:
// matchPhrasePrefix — typical locate-search query
{"type": "matchPhrasePrefix", "field": "all", "operator": "and", "query": "%%SEARCH_PHRASE%%"}
// wildcard — suffix wildcard on a specific keyword attribute
{"type": "wildcard", "field": "at_5120002.keyword", "query": "%%SEARCH_PHRASE%%*"}
// bool — combine must + should
{
"type": "bool",
"must": [{"type": "matchPhrasePrefix", "field": "all", "query": "%%SEARCH_PHRASE%%"}],
"should": [{"type": "terms", "field": "at_5010001.keyword", "values": ["active"]}]
}
Geometry and sharedSemantics
sharedSemantics is a LIDS metadata concept where multiple graphical child feature types share the attributes of a semantic parent type but carry their own geometry. Examples: a parcel (semantic parent) with a centroid symbol (child type, Point) and a polygon (child type, Surface).
Consequences for locate-search configuration:
- Only semantic parent types can appear in
"types". Child shared-semantics types are indexed under the parent's type ID. Including a child type ID directly will return no results. - Multiple geometries per document. When a semantic type has shared-semantics children, Elasticsearch stores all geometries (one per child) in the
"geometries"array of the indexed document. - locate-search creates one result per geometry. Because
LidsElasticProviderStrategyiterates the"geometries"array, a single feature can produce multiple locate-search hits — one for each stored geometry. - Restrict geometry types with
"geometries". To avoid duplicate hits or unwanted geometry types, add"geometries": ["ft_parcel_face"](feature type IDs from metadata) to the requestBody. Only geometries whosegeometryTypeIdmatches are returned; hits with no matching geometry are dropped entirely. - Geo-shape spatial filter (
geoShapequery) operates onsearch_geometry, which is the mergedGeometryCollectionof all geometries for the feature — it covers all child geometries in one go.
Example: semantic parent type ft_parcel_area has two shared-semantics children: ft_parcel_face carrying its polygon geometry and ft_parcel_point carrying its centroid geometry. To return only the face geometry (and avoid duplicate hits):
{
"types": ["ft_parcel_area"],
"query": {"type": "matchPhrasePrefix", "field": "all", "operator": "and", "query": "%%SEARCH_PHRASE%%"},
"size": 20,
"geometries": ["ft_parcel_face"]
}
5) Ready-to-Use Configuration Recipes
Recipe A - External address search (GeoJSON)
Use when users search addresses from external source.
<ber:locateSearchProvider id="swtopo_address" type="rest" providerType="geojson"
name="Swisstopo addresses" order="3" defaultColor="#db9909" defaultIcon="ic_adresse" coordinatesOrder="yx">
<ber:locateSearchCategoryArray>
<ber:locateSearchCategory id="address" name="Address" color="#db9909" icon="ic_adresse"/>
</ber:locateSearchCategoryArray>
<ber:commonRestInputConfiguration method="GET" removeBlanks="true">
<ber:url>https://api3.geo.admin.ch/rest/services/api/SearchServer?searchText=%%SEARCH_PHRASE%%&origins=address&type=locations&sr=4326&limit=10&geometryFormat=geojson</ber:url>
</ber:commonRestInputConfiguration>
<ber:categorySource type="property" name="origin"/>
<ber:responseForm><ber:name>label</ber:name></ber:responseForm>
</ber:locateSearchProvider>
Business tips:
- Keep
orderlower if addresses must appear near top. removeBlanks="true"is useful if the API expects compact address search terms.
Recipe B - External parcel/administrative search (GeoJSON)
Use when one provider should return multiple public categories.
<ber:locateSearchProvider id="swtopo_parcel" type="rest" providerType="geojson"
name="Swisstopo parcels" order="1" defaultColor="#db09cd" defaultIcon="info" coordinatesOrder="yx">
<ber:locateSearchCategoryArray>
<ber:locateSearchCategory id="gg25" name="Municipality" color="#db09cd" icon="ic_gemeinde"/>
<ber:locateSearchCategory id="parcel" name="Parcel" color="#33db09" icon="ic_parzelle"/>
</ber:locateSearchCategoryArray>
<ber:commonRestInputConfiguration method="GET">
<ber:url>https://api3.geo.admin.ch/rest/services/api/SearchServer?searchText=%%SEARCH_PHRASE%%&origins=gg25,parcel&type=locations&sr=4326&limit=10&geometryFormat=geojson</ber:url>
</ber:commonRestInputConfiguration>
<ber:categorySource type="property" name="origin"/>
<ber:responseForm><ber:name>label</ber:name></ber:responseForm>
</ber:locateSearchProvider>
Business tips:
- Categories let you brand each result type with distinct icon/color.
- This is ideal when a single API returns mixed object families.
Recipe C1 - Multiple LIDS feature types, no shared semantics
Use when searching across several independent feature types (each has its own geometry, no shared-semantics children).
<ber:locateSearchProvider id="lids_water" type="rest" providerType="lidsElastic"
name="LIDS water" order="5" defaultColor="#0000FF" defaultIcon="ic_demo">
<ber:locateSearchCategoryArray>
<ber:locateSearchCategory id="ft_5010100" name="Pumping Station" icon="ic_5010100"/>
<ber:locateSearchCategory id="ft_5012100" name="Main Pipeline Segment" color="#0abab5" icon="ic_5012100"/>
</ber:locateSearchCategoryArray>
<ber:commonRestInputConfiguration method="POST">
<ber:url>/rest/search/features</ber:url>
<ber:requestBody>
{
"types": ["ft_5010100", "ft_5012100"],
"query": {
"type": "matchPhrasePrefix",
"field": "all",
"operator": "and",
"query": "%%SEARCH_PHRASE%%"
},
"size": 20
}
</ber:requestBody>
</ber:commonRestInputConfiguration>
<ber:responseForm><ber:name>featureInfo</ber:name></ber:responseForm>
</ber:locateSearchProvider>
Business tips:
- List all relevant feature type IDs in
types. Each type appears as a separate category in results. - No
geometriesfilter needed — each feature has exactly one geometry.
Recipe C2 - Single LIDS feature type with shared semantics
Use when the semantic parent type (ft_parcel_area) has a shared-semantics child type (ft_parcel_face) that carries its own geometry. Without filtering, locate-search would return one hit per geometry (i.e. duplicate hits). Use "geometries" to keep only the desired geometry type.
<ber:locateSearchProvider id="lids_orgunit" type="rest" providerType="lidsElastic"
name="LIDS parcel" order="4" defaultColor="#00FF00" defaultIcon="ic_demo">
<ber:locateSearchCategoryArray>
<ber:locateSearchCategory id="ft_parcel_area" name="Parcel area" icon="ic_5060000"/>
</ber:locateSearchCategoryArray>
<ber:commonRestInputConfiguration method="POST">
<ber:url>/rest/search/features</ber:url>
<ber:requestBody>
{
"types": ["ft_parcel_area"],
"query": {
"type": "matchPhrasePrefix",
"field": "all",
"operator": "and",
"query": "%%SEARCH_PHRASE%%"
},
"geometries": ["ft_parcel_face"],
"size": 20
}
</ber:requestBody>
</ber:commonRestInputConfiguration>
<ber:responseForm><ber:name>featureInfo</ber:name></ber:responseForm>
</ber:locateSearchProvider>
Business tips:
typescontains only the shared semantics parents — shared-semantics child types cannot be searched directly.geometrieslists the child feature type ID whose geometry you want to show on the map. Omitting it would produce one locate-search hit per stored geometry (i.e. duplicate hits for each feature).- The category ID in
locateSearchCategoryArrayshould match the semantic parent type ID (ft_parcel_area), since that is what the search result carries as its type.
5) Business Decision Rules
- Priority of providers: control with
order; smaller number means higher visibility priority. - User-facing naming: use meaningful
nameand categorynamevalues (business terms, not technical IDs). - Branding consistency: define both provider defaults and category-specific overrides.
- Search phrase handling:
removeBlanks="true"for sources that fail on spaces.replaceBlanksfor sources expecting+or custom separator.- otherwise keep default encoding behavior.
- Coordinate order: if map markers appear in wrong location, switch
coordinatesOrderbetweenxyandyx.
6) Minimum Safe Checklist Before Go-Live
- Every provider has unique
id. providerTypeandmethodmatch the use case:- GeoJSON -> usually
GET - LIDS Elastic ->
POST+/rest/search/features
- GeoJSON -> usually
url(andrequestBodyfor POST) includes%%SEARCH_PHRASE%%where user text should go.- All expected source categories are mapped in
locateSearchCategoryArray. responseForm/namepoints to a field that actually exists in response (label,featureInfo, etc.).- Colors/icons are set (at least provider defaults).
- For GeoJSON,
categorySource type="property" name="..."matches real response property. - Coordinates display correctly on map (
coordinatesOrder).
7) Common Mistakes to Avoid
- Using
providerType="lidsElastic"withmethod="GET". - Forgetting
%%SEARCH_PHRASE%%, causing static or empty search behavior. - Category IDs not matching source values (results appear without expected labels/icons).
- Omitting fallback
defaultColoranddefaultIcon, causing inconsistent UI. - Setting both
removeBlanksandreplaceBlanksin same provider.
8) Quick Starter Template (Copy, Then Adjust)
<ber:locateSearchProvider id="my_provider" type="rest" providerType="geojson"
name="My Provider" order="1" defaultColor="#3A7AFE" defaultIcon="info" coordinatesOrder="yx">
<ber:locateSearchCategoryArray>
<ber:locateSearchCategory id="cat1" name="Category 1" color="#3A7AFE" icon="ic_cat1"/>
</ber:locateSearchCategoryArray>
<ber:commonRestInputConfiguration method="GET">
<ber:url>https://example.org/search?q=%%SEARCH_PHRASE%%&geometryFormat=geojson</ber:url>
</ber:commonRestInputConfiguration>
<ber:categorySource type="property" name="origin"/>
<ber:responseForm><ber:name>label</ber:name></ber:responseForm>
</ber:locateSearchProvider>
If you are configuring internal LIDS Elasticsearch instead, switch to:
providerType="lidsElastic"method="POST"url->/rest/search/features- add JSON
<ber:requestBody>with yourtypesand query.