> For the complete documentation index, see [llms.txt](https://docs.mapbox.com/android/ja/search/llms.txt)

# Data providers

The Mapbox Search SDK for Android lets developers to attach their own places, POIs, and address information to [`SearchEngine`](https://docs.mapbox.com/android/search/api/core/2.28.2/sdk/com.mapbox.search/-search-engine/) via data providers. Engines will index the provided data and use this data during forward geocoding and category search requests.

### Indexable record

[`IndexableRecord`](https://docs.mapbox.com/android/search/api/core/2.28.2/sdk/com.mapbox.search.record/-indexable-record/) stores place, POI, and address information that can later be used by both users and the Search SDK. The Search SDK uses information from `IndexableRecord` to prepare the [data provider engine](#data-provider-engine) and construct search results.

> **Note: Retrieve IndexableRecord from SearchResult**
> 
> You can retrieve `IndexableRecord` from [`SearchResult.indexableRecord`](https://docs.mapbox.com/android/search/api/core/2.28.2/sdk/com.mapbox.search.result/-search-result/indexable-record.html), which is non null if [`SearchResult`](https://docs.mapbox.com/android/search/api/core/2.28.2/sdk/com.mapbox.search.result/-search-result/) has been constructed from `IndexableRecord`:`kotlinval searchResult: SearchResult = // ...val record = searchResult?.indexableRecord`

### Data provider

[`IndexableDataProvider`](https://docs.mapbox.com/android/search/api/core/2.28.2/sdk/com.mapbox.search.record/-indexable-data-provider/) has two main responsibilities:

1.  Store `IndexableRecords` and provide read and write access so the Search SDK is able to retrieve and add records.
2.  Keep the [data provider engine](#data-provider-engine) up to date to guarantee all indexable records are available during search.

> **Note: Priority**
> 
> Each indexable record has an associated priority that helps search engines determine the ranking of search results constructed from indexable records. The priority of a record is equal to the priority of the data provider which is determined by `IndexableDataProvider.priority` property.

### Data provider engine

[`IndexableDataProviderEngine`](https://docs.mapbox.com/android/search/api/core/2.28.2/sdk/com.mapbox.search.record/-indexable-data-provider-engine/) is a search index that can be used by multiple search engines during search requests after processing. If you want search engines to be able to search across your data, add all necessary indexable records to the engine during the [`IndexableDataProvider.registerIndexableDataProviderEngine()`](https://docs.mapbox.com/android/search/api/core/2.28.2/sdk/com.mapbox.search.record/-indexable-data-provider/register-indexable-data-provider-engine.html) operation or later, when data will become available:

```kotlin
class CustomDataProvider : IndexableDataProvider<CustomIndexableRecord> {

    private val dataProviderEngines: MutableList<IndexableDataProviderEngine> = mutableListOf()
    private val records: MutableList<IndexableRecord> = mutableListOf()

    /**
     * Invoked when `CustomDataProvider` is registered in a `SearchEngine`.
     */
    override fun registerIndexableDataProviderEngine(
        dataProviderEngine: IndexableDataProviderEngine,
        executor: Executor,
        callback: CompletionCallback<Unit>
    ): AsyncOperationTask {
        synchronized(this) {
            dataProviderEngines.add(dataProviderEngine)
            dataProviderEngine.upsertAll(records)
        }
        executor.execute {
            callback.onComplete(Unit)
        }
        return CompletedAsyncOperationTask
    }

    /**
     * Invoked when search records become available.
     */
    private fun onDataLoaded(customData: List<CustomIndexableRecord>) {
        synchronized(this) {
            records.addAll(customData)
            dataProviderEngines.forEach { engine ->
                engine.upsertAll(records)
            }
        }
    }

    // ...

    private object CompletedAsyncOperationTask : AsyncOperationTask {

        override val isDone: Boolean
            get() = true

        override val isCancelled: Boolean
            get() = false

        override fun cancel() {
            // Do nothing
        }
    }
}
```

`IndexableDataProviderEngine` is thread-safe and can be called from different threads.

> **Note: Consider using data provider engine only from background thread**
> 
> Even though in most cases changing the index used in the data provider engine takes a few milliseconds, sometimes it may take longer for operation to complete (for example, when the data provider engine is used by a search engine or when user adds more than 10,000 records).

## Built-in data providers

The Mapbox Search SDK for Android has built-in data providers that are attached to each instance of the `SearchEngine` created with [SearchEngine.createSearchEngineWithBuiltInDataProviders()](https://docs.mapbox.com/android/search/api/core/2.28.2/sdk/com.mapbox.search/-search-engine/-companion/create-search-engine-with-built-in-data-providers.html). If an instance of the `SearchEngine` is instantiated with [SearchEngine.createSearchEngine()](https://docs.mapbox.com/android/search/api/core/2.28.2/sdk/com.mapbox.search/-search-engine/-companion/create-search-engine.html), it will not have any data providers registered by default.

The Search SDK provides two built-in data providers:

-   [`Search history`](https://docs.mapbox.com/android/ja/search/guides/search-engine/search-history/) - data provider which is designed to store the most recent search results selected on a device.
-   [`Favorites`](https://docs.mapbox.com/android/ja/search/guides/search-engine/favorites/) - data provider which is designed to store user's favorite places, addresses, POIs.

You will learn more about these data providers later in this guide.

## Custom data providers

The Mapbox Search SDK for Android allows you create your own data providers if you want to introduce custom POIs or addresses to the search engine during the search.

> **Related content (example): [Custom data provider](https://docs.mapbox.com/android/ja/search/examples/custom-provider/)**
> 
> Search across POIs provided by custom data provider

First, you should create a record class that will store all the data about places, POIs, and addresses that you have. Implement an `IndexableRecord` interface. We recommend using a Kotlin `data class` and `@Parcelize` annotation from the [`kotlin-parcelize` plugin](https://developer.android.com/kotlin/parcelize) to ease implementation:

```kotlin
@Parcelize
data class CustomRecord(
    override val id: String,
    override val name: String,
    override val coordinate: Point,
    override val type: SearchResultType,
    override val descriptionText: String?,
    override val address: SearchAddress?,
    override val routablePoints: List<RoutablePoint>?,
    override val categories: List<String>?,
    override val makiIcon: String?,
    override val metadata: SearchResultMetadata?,
    override val indexTokens: List<String>,
) : IndexableRecord
```

Then, implement an [`IndexableDataProvider`](https://docs.mapbox.com/android/search/api/core/2.28.2/sdk/com.mapbox.search.record/-indexable-data-provider/) interface that will be used as a source of custom records and will update the search engine index associated with the provided `IndexableDataProviderEngine` instance.

> **Note: Keep data provider engine up-to-date**
> 
> Search engines will only be able to search across custom data if you've added custom data to `IndexableDataProviderEngine`. Make sure you've provided your data to the data provider engine once data is available. Read more about data provider engines in [data provider engine section](#data-provider-engine).

And finally, register custom data provider in your `SearchEngine`:

```kotlin
val searchEngine: SearchEngine = //...
val customDataProvider: CustomDataProvider = // ...
val task = searchEngine.registerDataProvider(
    customDataProvider,
    callback = object : CompletionCallback<Unit> {
        override fun onComplete(result: Unit) {
        }

        override fun onError(e: Exception) {
        }
    }
)
```

> **Note: Unregister data providers when they are not needed**
> 
> If you want to remove your custom data from search engine indexes, unregister your custom data provider from the `SearchEngine`:`kotlinval task = searchEngine.unregisterDataProvider( customDataProvider, callback = object : CompletionCallback<Unit> { override fun onComplete(result: Unit) { } override fun onError(e: Exception) { } })`

## Indexable records exclusion

Indexable records can be excluded from a search response by modifying [SearchOptions.ignoreIndexableRecords](https://docs.mapbox.com/android/search/api/core/2.28.2/sdk/com.mapbox.search/-search-options/ignore-indexable-records.html) and [CategorySearchOptions.ignoreIndexableRecords](https://docs.mapbox.com/android/search/api/core/2.28.2/sdk/com.mapbox.search/-category-search-options/ignore-indexable-records.html), for example,

```kotlin
val searchOption = SearchOptions(ignoreIndexableRecords = true)
val categorySearchOptions = CategorySearchOptions(ignoreIndexableRecords = true)
```