Building an Address Search Function with Amazon Location SDK and API Key Function
Tags: maplibre, amazonlocationservice, aws, foss4g
Published: 2023-10-24 10:07:31

![img](https://memo.dayjournal.dev/images/try-104_02.png)

<br>

### I built an address search function with Amazon Location SDK and API key. :tada:  

In the past, to use the Amazon Location Service, you had the option of [configuring it manually](https://dev.to/aws-builders/building-an-address-lookup-function-with-amazon-location-service-3fdm) or [using Amplify Geo](https://dev.to/aws-builders/building-an-address-search-function-with-amplify-geo-bjf). However, with the release of the [Amazon Location SDK](https://docs.aws.amazon.com/location/latest/developerguide/dev-location-libraries.html) and API Key feature this year, more options are now available, and the Amazon Location SDK makes manual configuration easier. I would like to explain the address search feature using this new functionality in this article.

The created environment is available on GitHub. Please use it! 

{% embed https://github.com/mug-jp/maplibregljs-amazon-location-service-place-indexes-starter %}

<br>

## Advance Preparation

- Create an API key for Amazon Location Service

[Amazon Location Service #004 - API Key Creation (Maps)](https://memo.dayjournal.dev/memo/amazon-location-service-004)
[Amazon Location Service #005 - API Key Creation (Geocoding)](https://memo.dayjournal.dev/memo/amazon-location-service-005)

- Use the built environment to get started with MapLibre GL JS and Amazon Location Service easily

[maplibregljs-amazon-location-service-starter](https://github.com/mug-jp/maplibregljs-amazon-location-service-starter)

Execution environment

- node v20.6.1
- npm v9.8.1

<br>

## How to use the MapLibre GL JS and Amazon Location Service starter
Use the existing starter to build an address search function. Fork or download the package to your local environment and verify it works.

Install the package

```sh
npm install
```

Start local server

```sh
npm run dev
```

![img](https://memo.dayjournal.dev/images/try-104_03.png)

<br>

## Install Amazon Location SDK
Next, install the necessary libraries for the Amazon Location SDK. Installing it will make it easier to authenticate the API and combine it with MapLibre GL JS.

Install the AWS SDK. "client-location" is an SDK that allows you to manipulate the Amazon Location Service.

```sh
npm install @aws-sdk/client-location
```

Install "amazon-location-utilities-auth-helper," a library that facilitates authentication with Amazon Location Service API keys and Cognito.

```sh
npm install @aws/amazon-location-utilities-auth-helper
```

Install "amazon-location-utilities-datatypes," a library that converts Amazon Location Service responses to GeoJSON format.

```sh
npm install @aws/amazon-location-utilities-datatypes
```

<br>

I contributed to "amazon-location-utilities-datatypes" to add an optional feature because it was sometimes difficult to use in combination with MapLibre GL JS!

{% embed https://github.com/aws-geospatial %}

<br>
<br>

## Building an Address Search Function
Finally, we will build the address search function. Some files are changed from the starter.

Overall Configuration
![img](https://memo.dayjournal.dev/images/try-104_04.png)

<br>

#### package.json

```json
{
  "name": "maplibregljs-amazon-location-service-place-indexes-starter",
  "version": "3.3.1",
  "description": "",
  "scripts": {
    "dev": "vite",
    "build": "tsc && vite build",
    "preview": "vite preview"
  },
  "keywords": [],
  "author": "MapLibre User Group Japan",
  "license": "ISC",
  "devDependencies": {
    "typescript": "^5.2.2",
    "vite": "^4.4.9"
  },
  "dependencies": {
    "@aws-sdk/client-location": "^3.433.0",
    "@aws/amazon-location-utilities-auth-helper": "^1.0.2",
    "@aws/amazon-location-utilities-datatypes": "^1.0.3",
    "maplibre-gl": "^3.3.1"
  }
}
```

<br>

#### .env
Set the region, map API key, map name, geocoding API key, and geocoding name created in the preliminaries to the env file.

```env
VITE_REGION = xxxxx
VITE_MAP_API_KEY = v1.public.xxxxx
VITE_MAP_NAME = xxxxx
VITE_PLACE_API_KEY = v1.public.xxxxx
VITE_PLACE_NAME = xxxxx
```

<br>

/src
#### main.ts

```typescript
import './style.css'
import 'maplibre-gl/dist/maplibre-gl.css';
import maplibregl from 'maplibre-gl';
import { LocationClient, SearchPlaceIndexForTextCommand } from "@aws-sdk/client-location";
import { placeToFeatureCollection } from '@aws/amazon-location-utilities-datatypes';
import { withAPIKey } from '@aws/amazon-location-utilities-auth-helper';

const region = import.meta.env.VITE_REGION;
const mapApiKey = import.meta.env.VITE_MAP_API_KEY;
const mapName = import.meta.env.VITE_MAP_NAME;
const placeApiKey = import.meta.env.VITE_PLACE_API_KEY;
const placeName = import.meta.env.VITE_PLACE_NAME;

async function initialize() {
    const authHelper = await withAPIKey(placeApiKey);
    const client = new LocationClient({
        region: region,
        ...authHelper.getLocationClientConfig()
    });

    const input = {
        IndexName: placeName,
        Text: "サッポロファクトリー",
    };
    const command = new SearchPlaceIndexForTextCommand(input);
    const response = await client.send(command);
    const featureCollection = placeToFeatureCollection(response, {
        flattenProperties: true
    });

    const map = new maplibregl.Map({
        container: 'map',
        style: `https://maps.geo.${region}.amazonaws.com/maps/v0/maps/${mapName}/style-descriptor?key=${mapApiKey}`,
        center: [139.767, 35.681],
        zoom: 11,
    });
    map.addControl(
        new maplibregl.NavigationControl({
            visualizePitch: true,
        })
    );

    map.on('load', function () {
        map.addSource("search-result", {
            type: "geojson",
            data: featureCollection
        });
        map.addLayer({
            'id': "search-result",
            'type': 'circle',
            'source': 'search-result',
            'layout': {},
            'paint': {
                'circle-color': '#007cbf',
                'circle-radius': 10
            }
        });
        map.on('click', 'search-result', (e) => {
            const coordinates = e.lngLat;
            const description = e.features![0].properties['Place.Label'];
            new maplibregl.Popup()
                .setLngLat(coordinates)
                .setHTML(description)
                .addTo(map);
        });
        map.on('mouseenter', 'search-result', () => {
            map.getCanvas().style.cursor = 'pointer';
        });
        map.on('mouseleave', 'search-result', () => {
            map.getCanvas().style.cursor = '';
        });
    });
}
initialize();
```

Define the Amazon Location SDK.

```typescript
import { LocationClient, SearchPlaceIndexForTextCommand } from "@aws-sdk/client-location";
import { placeToFeatureCollection } from '@aws/amazon-location-utilities-datatypes';
import { withAPIKey } from '@aws/amazon-location-utilities-auth-helper';
```

Set up authentication for the API key.

```typescript
const authHelper = await withAPIKey(placeApiKey);
const client = new LocationClient({
    region: region,
    ...authHelper.getLocationClientConfig()
});
```

Geocoding from text.

```typescript
const input = {
    IndexName: placeName,
    Text: "サッポロファクトリー",
};
const command = new SearchPlaceIndexForTextCommand(input);
const response = await client.send(command);
```

Convert the geocoding response to GeoJSON.

```typescript
const featureCollection = placeToFeatureCollection(response, {
    flattenProperties: true
});
```

<br>

Let's check with a simple local server.

```sh
npm run dev
```

<br>

You can combine the Amazon Location SDK with the API key functionality to display the results of an address search!
![img](https://memo.dayjournal.dev/images/try-104_05.png)  

<br>

Here are some other examples!

<br>

Geocoding from ID.

```typescript
import { LocationClient, GetPlaceCommand } from "@aws-sdk/client-location";

...

    const input = {
        IndexName: placeName,
        PlaceId: "AQABAFkA9d5eLnjB7XKy9_p0QX3oXD4nrLodHDtIvvzOwEyHbBx9m7LhmUP9WoNILhCrNzsL_DzOmUqagzNOgEabayDDLe6Oxh0rXolepvlZamPS5Q4KX41udsz856yYG6UdXqO6JmoLazImn-Isq2p20k5q_0902-uClFkGTw"
    };
    const command = new GetPlaceCommand(input);

...
```

![img](https://memo.dayjournal.dev/images/try-104_06.png) 

<br>

Reverse geocoding from the specified location.

```typescript
import { LocationClient, SearchPlaceIndexForPositionCommand } from "@aws-sdk/client-location";

...

    const input = {
        IndexName: placeName,
        Position: [139.767, 35.681],
    };
    const command = new SearchPlaceIndexForPositionCommand(input);

...
```

![img](https://memo.dayjournal.dev/images/try-104_07.png) 

<br>

Related Articles
{% link https://dev.to/aws-heroes/building-a-map-application-with-maplibre-gl-js-and-amazon-location-service-api-key-functionality-29db %}
{% link https://dev.to/mug-jp/building-a-map-application-with-maplibre-gl-js-and-svelte-pg6 %}
{% link https://dev.to/aws-heroes/trying-to-display-an-amazon-location-service-map-in-qgis-5el3 %}
{% link https://dev.to/aws-heroes/use-3d-map-library-with-api-key-function-of-amazon-location-service-c6a %}
{% link https://dev.to/aws-heroes/amazon-location-service-and-aws-amplify-to-use-various-map-library-4mmk %}

<br>

References
[Amazon Location Service](https://aws.amazon.com/location)
[MapLibre GL JS](https://maplibre.org/)