The RelatedItems component computes search parameters to fetch related items.
You can pass a hit as the reference for computing search parameters and retrieving the related items.
To add RelatedItems to your search experience, use the following components:
Searcher. A new HitsSearcher that handles your searches for related items.
HitsView. A data class representing a search result.
T. An Indexable data class representing the hit to get related items.
This component acts similarly to the Hits component,
but it only modifies the results.
Examples
You can use deserialize to convert raw hits into your own data class using the Serializable annotation.
import com.algolia.instantsearch.core.Indexable
class MyActivity : AppCompatActivity() {
val searcher = HitsSearcher(
applicationID = "YourApplicationID",
apiKey = "YourSearchOnlyAPIKey",
indexName = "YourIndexName"
)
val connection = ConnectionHandler()
val adapter = ProductAdapter()
val product = Product(
objectID = "objectID123",
name = "productName",
brand = "Amazon",
categories = listOf("Streaming Media Players", "TV & Home Theater")
)
val matchingPatterns = listOf(
MatchingPattern("brand", 1, Product::brand),
MatchingPattern("categories", 2, Product::categories)
)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
connection += searcher.connectRelatedHitsView(adapter, product, matchingPatterns) { response ->
response.hits.deserialize(Product.serializer())
}
searcher.searchAsync()
}
override fun onDestroy() {
super.onDestroy()
connection.disconnect()
searcher.cancel()
}
}
@Serializable
data class Product(
override val objectID: String,
val name: String,
val brand: String,
val categories: List<String>
) : Indexable
class ProductAdapter : RecyclerView.Adapter<ProductViewHolder>(), HitsView<Product> {
private var products: List<Product> = listOf()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ProductViewHolder {
return ProductViewHolder(parent.inflate(R.layout.list_item_product))
}
override fun onBindViewHolder(holder: ProductViewHolder, position: Int) {
val item = products[position]
holder.bind(item)
}
override fun setHits(hits: List<Product>) {
products = hits
notifyDataSetChanged()
}
override fun getItemCount(): Int {
return products.size
}
}
class ProductViewHolder(private val view: View) : RecyclerView.ViewHolder(view) {
fun bind(product: Product) {
view.itemName.text = product.name
}
}
Compose UI
import com.algolia.instantsearch.core.Indexable
class MyActivity : AppCompatActivity() {
private val searcher = HitsSearcher(
applicationID = "YourApplicationID",
apiKey = "YourSearchOnlyAPIKey",
indexName = "YourIndexName"
)
private val relatedItemsSearcher = HitsSearcher(
applicationID = "YourApplicationID",
apiKey = "YourSearchOnlyAPIKey",
indexName = "YourIndexName"
)
private val productsHits = HitsState<Product>()
private val relatedItems = HitsState<Product>()
private val matchingPatterns: List<MatchingPattern<Product>> = listOf(
MatchingPattern("brand", 1, Product::brand),
MatchingPattern("categories", 2, Product::categories)
)
private var relatedItemConnection: Connection? = null
private val productsSearchConnection = searcher
.connectHitsView(productsHits) { it.hits.deserialize(Product.serializer()) }
.also { it.connect() }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MyRelatedItemsScreen(
hits = productsHits.hits,
relatedItems = relatedItems.hits,
onProductClick = ::relatedItemsOf
)
}
searcher.query = searcher.query.copy(hitsPerPage = 3) // Limit to 3 results
configureSearcher(searcher)
configureSearcher(relatedItemsSearcher)
searcher.searchAsync()
}
private fun relatedItemsOf(product: Product) {
relatedItemConnection?.disconnect()
relatedItemConnection = relatedItemsSearcher.connectRelatedHitsView(
relatedItems, product, matchingPatterns
) { response ->
response.hits.deserialize(Product.serializer())
}
relatedItemConnection?.connect()
relatedItemsSearcher.searchAsync()
}
override fun onDestroy() {
super.onDestroy()
searcher.cancel()
relatedItemsSearcher.cancel()
relatedItemConnection?.disconnect()
productsSearchConnection.disconnect()
}
}
Parameters
The reference hit to compute the search parameters to send to Algolia.You can retrieve this hit from any location (app state, your backend, the history, etc.)val product = Product(
objectID = "objectID123",
name = "productName",
brand = "Amazon",
categories = listOf("Streaming Media Players", "TV & Home Theater")
)
matchingPatterns
List<MatchingPattern<T>>
required
A schema that creates scored filters
based on the hit’s attributes.In the example below, the brand value gets a score of 1 while the category values get a score of 2.import com.algolia.instantsearch.core.Indexable
data class Product(
override val objectID: String,
val name: String,
val brand: String,
val categories: List<String>
) : Indexable
val matchingPatterns: List<MatchingPattern<Product>> = listOf(
MatchingPattern("brand", 1, Product::brand),
MatchingPattern("categories", 2, Product::categories)
)
The hit above would generate the following search parameters:{
"sumOrFiltersScores": true,
"facetFilters": ["objectID:-1234"],
"optionalFilters": [
["brand:Amazon<score=1>"],
[
[
"categories:TV & Home Theater<score=2>",
"categories:Streaming Media Players<score=2>"
]
]
]
}
presenter
(SearchResponse) -> List<T>
required
A function that transforms the search response into a list of results of your T class.import com.algolia.client.model.search.SearchResponse
val presenter: (SearchResponse) -> List<Product> = { response ->
response.hits.deserialize(Product.serializer())
}
searcher.connectRelatedHitsView(adapter, product, matchingPatterns, presenter)
Last modified on February 9, 2026