{"slug": "maximum-marginal-relevance-and-elastic-diversifying-search-results", "title": "Maximum Marginal Relevance and Elastic: Diversifying Search Results", "summary": "Elasticsearch has introduced a blog post demonstrating how to implement Maximum Marginal Relevance (MMR) to diversify search results, using a fashion product catalog as an example. The MMR algorithm balances relevance and diversity by iteratively selecting items that are relevant to the query but dissimilar to already chosen results, controlled by a lambda parameter. The implementation uses vector similarity for relevance scoring and includes code examples for reranking search results.", "body_md": "[Blog](/search-labs/blog)\n\n# Diversifying search results with Maximum Marginal Relevance\n\nImplementing the Maximum Marginal Relevance (MMR) algorithm with Elasticsearch and Python. This blog includes code examples for vector search reranking.\n\nWhen you search for \"pants\" in an e-commerce catalog, do you really want to see 10 variations of the same black capris? Probably not. You'd likely prefer a diverse selection showing different styles, colors, and types of pants. This is where Maximum Marginal Relevance (MMR) comes in *—* a powerful technique for balancing relevance with diversity in search results.\n\nIn this blog, we'll explore how to implement MMR with Elasticsearch to create more diverse and useful search results, using a fashion product catalog as our example.\n\n**The problem: When relevance isn't enough**\n\nTraditional search systems optimize for one thing: relevance. They find items that best match your query and rank them by similarity scores. This works well for many use cases, but it can lead to redundant results.\n\nConsider searching for \"pants\" in a fashion catalog. A pure relevance-based search might return:\n\nBlack capris (score: 0.682)\n\nBlack capris from another brand (score: 0.681)\n\nMore black capris (score: 0.680)\n\nEven more black capris (score: 0.680)\n\n...you get the idea\n\nWhile these are all highly relevant to \"pants\", they're not particularly helpful for a user trying to explore different options. What we need is a way to maintain relevance while promoting diversity.\n\n**Enter Maximum Marginal Relevance**\n\n[MMR](https://www.cs.cmu.edu/~jgc/publication/The_Use_MMR_Diversity_Based_LTMIR_1998.pdf) is an algorithm that elegantly solves this problem by balancing two competing objectives:\n\n**Relevance**: How well items match the query** Diversity**: How different items are from each other\n\nThe algorithm works iteratively, selecting items that are relevant to the query but different from already selected items. This ensures that each additional result adds new information rather than redundancy.\n\n**How MMR works**\n\nThe MMR algorithm follows a simple but effective process:\n\nStart by selecting the most relevant item (highest score)\n\nFor each remaining item, calculate an MMR score that combines: Its relevance to the query and its dissimilarity to already selected items\n\nSelect the item with the highest MMR score\n\nRepeat until you have enough results\n\nThe key insight is the MMR scoring formula:\n\n```\nMMR Score = λ × relevance - (1 - λ) × max_similarity_to_selected\n```\n\nThe λ parameter controls the trade-off, where λ = 1.0 is pure relevance (no diversity) and λ = 0.0: pure diversity (ignore relevance).\n\nMMR doesn’t dictate *how* you score relevance *—* it just needs a number. That could come from BM-25, a learned ranker, or any custom metric you like. Because BM-25 relies on per-term statistics stored in postings lists that aren’t available on the client, we’ll use [vector similarity](https://www.elastic.co/search-labs/blog/introduction-to-vector-search) as our relevance function for this blog. This lets us compute relevance elegantly by taking the dot product.\n\n**Implementing MMR**\n\nLet's see how to implement MMR for an image search system using Elasticsearch and multimodal embeddings. To showcase the effects of MMR we will be using the [paramaggarwal/fashion-product-images-dataset](https://www.kaggle.com/datasets/paramaggarwal/fashion-product-images-dataset) dataset.\n\nIn this blog post we will only focus on the retrieval and reranking, but you can find a [full end-to-end example](https://github.com/elastic/elasticsearch-labs/blob/main/supporting-blog-content/result-diversification/diversification.ipynb) in our search-labs GitHub repository.\n\nFirst, we need to search for similar items using vector similarity:\n\n``` python\ndef search_similar_images(es, index_name, query_vector, k=10):\n    \"\"\"Search for similar images using vector similarity\"\"\"\n    query = {\n        \"knn\": {\n            \"field\": \"image_vector\",\n            \"query_vector\": query_vector,\n            \"k\": k\n        },\n        \"_source\": [\"id\", \"image_url\"],\n        \"size\": k\n    }\n    \n    response = es.search(index=index_name, body=query)\n    return extract_results(response)\n```\n\nThis gives us our initial relevance-ranked results. Now, let's apply MMR to rerank them for diversity:\n\n``` python\ndef maximal_marginal_relevance(\n    query_embedding: List[float],\n    embedding_list: List[List[float]],\n    lambda_mult: float = 0.5, # value between 0.0 and 1.0\n    k: int = 4,\n) -> List[int]:\n    query_embedding_arr = np.array(query_embedding)\n\n    if min(k, len(embedding_list)) <= 0:\n        return []\n    if query_embedding_arr.ndim == 1:\n        query_embedding_arr = np.expand_dims(query_embedding_arr, axis=0)\n\n    # calcuate the similarity to the query for all reranking candidates\n    similarity_to_query = _cosine_similarity(query_embedding_arr, embedding_list)[0]\n    # start with the most similar item to the query\n    most_similar = int(np.argmax(similarity_to_query))\n    idxs = [most_similar]\n    selected = np.array([embedding_list[most_similar]])\n\n    # Iteratively select documents that maximize MMR score\n    while len(idxs) < min(k, len(embedding_list)):\n        best_score = -np.inf\n        idx_to_add = -1\n\n\t   # calulate the similarity between all candidate items and all selected items\n        similarity_to_selected = _cosine_similarity(embedding_list, selected)\n        \n\t   # look at all candidates \n        for i, query_score in enumerate(similarity_to_query):\n            if i in idxs:\n                continue\n\n\t\t # Find the highest similarity of this item to already selected items\n            redundant_score = max(similarity_to_selected[i])\n\t\t # Calculate MMR score\n            equation_score = (lambda_mult * query_score - (1 - lambda_mult) * redundant_score)\n            \n\t\t # select this item if it has the highest MMR score for this run\n            if equation_score > best_score:\n                best_score = equation_score\n                idx_to_add = i\n        \n        # append the item with the highest MMR score for this run to our list  \n        idxs.append(idx_to_add)\n        selected = np.append(selected, [embedding_list[idx_to_add]], axis=0)\n    return idxs\n```\n\n**The impact: Before and after MMR**\n\nLet's look at how MMR transforms search results for the query \"pants\":\n\n**Before MMR (pure relevance):**\n\nNotice the repetition? We see that most products are a dark shade with a straight cut.\n\n**After MMR (λ=0.5):**\n\nThe reranked results showcase diversity in many features such as colors, brands, target demographics, style and more. Each result adds new information, making the exploration experience more valuable.\n\n**Tuning MMR for your use case**\n\nThe beauty of MMR lies in its tunability. By adjusting the λ parameter, you can adapt the algorithm to different scenarios:\n\n**Product Discovery**(λ=0.3-0.5): Emphasize diversity to help users explore options** Precision Search**(λ=0.7-0.9): Prioritize relevance when users know what they want** Research Applications**(λ=0.5-0.7): Balance for comprehensive coverage\n\nYou can even make λ dynamic based on:\n\nQuery type (broad vs. specific)\n\nUser behavior (browsing vs. purchasing)\n\nResult set characteristics (high vs. low similarity)\n\n**Performance considerations**\n\nWhile MMR provides significant value, it does come with computational costs. The algorithm computes similarities between candidates and selected items. For production systems, consider limiting the reranking depth to a top k for results for the best tradeoff between impact and performance. Also, consider that retrieving the vectors will impact your performance, as it requires serialization of large amounts of data.\n\n**Beyond e-commerce: Other applications**\n\nWhile we've focused on fashion products and traditional search bars with result lists, MMR has broad applications. When using [Retrieval Augmented Generation (RAG) applications](https://www.elastic.co/search-labs/blog/retrieval-augmented-generation-rag), a request for \"great vacation spots\" could, without result diversification, yield results solely focused on Greek beaches. MMR, however, would diversify the output to include a range of vacation types, from relaxing beach holidays in Greece to adventurous hikes up an Icelandic volcano. Other use-cases could include:\n\n**News aggregation**: Show articles from different sources and perspectives** Document search**: Surface documents covering different aspects of a topic** Recommendation**: Suggest diverse movies, music, or content** Academic search**: Find papers from different research groups and methodologiesAnd countless more\n\n**Conclusion**\n\nMaximum Marginal Relevance transforms search from a pure relevance race into a balanced information retrieval system. By implementing MMR with Elasticsearch, you can deliver search results that are not just relevant but also informative and diverse.\n\nThe key is finding the right balance for your use case. Start with λ=0.7 for a relevance-leaning approach, then adjust based on user feedback and behavior. Your users will appreciate seeing a variety of relevant options rather than slight variations of the same thing.\n\nSometimes the second-best match that's different is more valuable than another perfect match that's redundant. That's the power of diversity in search.", "url": "https://wpnews.pro/news/maximum-marginal-relevance-and-elastic-diversifying-search-results", "canonical_source": "https://www.elastic.co/search-labs/blog/maximum-marginal-relevance-diversify-results", "published_at": "2026-07-30 08:01:26+00:00", "updated_at": "2026-07-30 08:22:23.803561+00:00", "lang": "en", "topics": ["machine-learning"], "entities": ["Elasticsearch", "Maximum Marginal Relevance", "MMR"], "alternates": {"html": "https://wpnews.pro/news/maximum-marginal-relevance-and-elastic-diversifying-search-results", "markdown": "https://wpnews.pro/news/maximum-marginal-relevance-and-elastic-diversifying-search-results.md", "text": "https://wpnews.pro/news/maximum-marginal-relevance-and-elastic-diversifying-search-results.txt", "jsonld": "https://wpnews.pro/news/maximum-marginal-relevance-and-elastic-diversifying-search-results.jsonld"}}