This website is currently under active development (Beta) 🚀. Some features are still work in progress.
Laravel Tutorial

Mastering Laravel MongoDB Full-Text Search: The Art of Relevancy with BM25 and Field Weighting

Admin User
Admin User
May 23, 2026
7 min read

Key Takeaways

  • Introduction to Full-Text Search and MongoDB Atlas Search
  • In today's data-rich applications, a powerful and accurate search feature is paramount. Users expect f...

In today's data-rich applications, a powerful and accurate search feature is paramount. Users expect fast, relevant results, even when dealing with large volumes of unstructured text. Traditional database queries often fall short for this, leading to the adoption of full-text search engines.

MongoDB Atlas Search, built on Apache Lucene, provides a robust, fully managed full-text search solution that integrates seamlessly with your MongoDB data. It offers advanced features like BM25 relevancy scoring and field weighting, allowing developers to fine-tune search result quality. This tutorial will guide you through implementing and optimizing full-text search in your Laravel application using MongoDB Atlas Search.

Prerequisites #

Before we begin, ensure you have the following:

  • An existing or new Laravel project.
  • A MongoDB Atlas account and a deployed cluster. If you don't have one, sign up for a free tier cluster.
  • The jenssegers/laravel-mongodb package installed in your Laravel project for MongoDB integration.

Step 1: Setting Up MongoDB Atlas Search Index #

The core of MongoDB Atlas Search lies in its indexes. These indexes define which fields are searchable, how they are analyzed, and how relevancy is scored. We'll create a basic index and then enhance it for relevancy tuning.

1. Navigate to Atlas UI and Create an Index #

  1. Log in to your MongoDB Atlas account.
  2. Navigate to your desired cluster.
  3. In the left sidebar, click on 'Search'.
  4. Click 'Create Search Index'.
  5. Choose 'JSON Editor' and click 'Next'.
  6. Select your database and collection (e.g., your_db.products).
  7. Name your index (e.g., default or product_search).
  8. Paste the following JSON configuration:
{
  "mappings": {
    "dynamic": false,
    "fields": {
      "name": {
        "type": "string",
        "analyzer": "lucene.standard",
        "searchAnalyzer": "lucene.standard"
      },
      "description": {
        "type": "string",
        "analyzer": "lucene.standard",
        "searchAnalyzer": "lucene.standard"
      }
    }
  },
  "synonyms": [
    {
      "name": "product_synonyms",
      "source": {
        "collection": "product_synonyms_collection"
      }
    }
  ]
}

This basic configuration makes the name and description fields searchable. The dynamic: false ensures only explicitly defined fields are indexed, which is good practice for control. We also include a placeholder for synonyms, which can be defined in a separate collection.

2. Understanding BM25 Indexing #

By default, MongoDB Atlas Search uses the BM25 (Best Match 25) algorithm for relevancy scoring. BM25 is a ranking function used by search engines to estimate the relevance of documents to a given search query. It considers factors like:

  • Term Frequency (TF): How often a term appears in a document.
  • Inverse Document Frequency (IDF): How rare a term is across all documents (rarer terms are more significant).
  • Document Length: Shorter documents matching the query might be considered more relevant than longer ones (normalized).

You typically don't configure BM25 directly, but rather influence its parameters through field weighting, which we'll cover next.

Step 2: Integrating MongoDB with Laravel #

Assuming you have jenssegers/laravel-mongodb installed and configured:

1. Database Configuration #

Ensure your .env file has the correct MongoDB connection details:

DB_CONNECTION=mongodb
DB_HOST=your_atlas_host
DB_PORT=27017
DB_DATABASE=your_db_name
DB_USERNAME=your_username
DB_PASSWORD=your_password
MONGODB_SRV=true # Set to true if using SRV record connection string

2. Create a Laravel Model #

Create a model for your collection, e.g., Product.php:

<?php

namespace App\Models;

use Jenssegers\Mongodb\Eloquent\Model;

class Product extends Model { protected $connection = 'mongodb'; protected $collection = 'products'; // Your collection name

protected $fillable = [
    'name',
    'description',
    'category',
    'price'
];

}

Step 3: Performing Full-Text Searches in Laravel #

To perform a search using MongoDB Atlas Search, you'll typically use the aggregation pipeline with the $search operator.

Example Search Query #

use App\Models\Product;

class ProductController extends Controller { public function search(Request $request) { $query = $request->input('q');

    if (empty($query)) {
        return response()->json([]);
    }

    $products = Product::raw(function($collection) use ($query) {
        return $collection->aggregate([
            [
                '$search' => [
                    'index' => 'product_search', // The name of your search index
                    'text' => [
                        'query' => $query,
                        'path' => ['name', 'description'] // Fields to search within
                    ]
                ]
            ],
            [
                '$project' => [
                    'name' => 1,
                    'description' => 1,
                    'category' => 1,
                    'price' => 1,
                    'score' => [ '$meta' => 'searchScore' ] // Include the search score
                ]
            ],
            ['$sort' => ['score' => -1]], // Sort by relevancy
            ['$limit' => 10]
        ]);
    });

    return response()->json($products);
}

}

In this example:

  • $search operator initiates the Atlas Search query.
  • index specifies which Atlas Search index to use.
  • text defines a text search query:
    • query is the search term.
    • path specifies the fields to search.
  • $project is used to shape the output, crucially including $meta: 'searchScore' to retrieve the relevancy score.
  • $sort orders results by score in descending order, showing the most relevant first.

Step 4: The Art of Relevancy: Field Weighting #

While BM25 provides a good baseline, you often need to tell the search engine that certain fields are more important than others. This is where field weighting comes in. For example, a match in the product name might be more significant than a match in the description.

Modifying the Atlas Search Index for Field Weighting #

Go back to your Atlas Search index configuration and modify the JSON to add weight to the name field:

{
  "mappings": {
    "dynamic": false,
    "fields": {
      "name": {
        "type": "string",
        "analyzer": "lucene.standard",
        "searchAnalyzer": "lucene.standard",
        "weight": {
          "score": 2 // Give 'name' field a weight of 2
        }
      },
      "description": {
        "type": "string",
        "analyzer": "lucene.standard",
        "searchAnalyzer": "lucene.standard"
      }
    }
  }
}

By assigning "weight": {"score": 2} to the name field, matches found in the name field will contribute twice as much to the overall relevancy score compared to matches in the description field. This directly influences the BM25 calculation, making results where the search term appears in the name rank higher.

Impact on Search Results #

With field weighting applied, if a user searches for "red shoes":

  • A product named "Red Shoes Deluxe" will likely rank higher than a product named "Deluxe Walking Shoes" with "red" appearing only once in its long description.
  • This simple adjustment can dramatically improve the user experience by surfacing the most relevant items first, based on your application's specific business logic and content hierarchy.

You can experiment with different weight values (e.g., 0.5, 1.5, 3) to fine-tune the results for various fields in your documents.

Advanced Topics (Briefly) #

  • Fuzzy Search: Use the fuzzy operator within text for typo tolerance.
  • Auto-Completion: Utilize the autocomplete operator for type-ahead suggestions.
  • Synonyms: Expand your search by defining synonym mappings in Atlas.
  • Custom Analyzers: Create specialized text analyzers for language-specific processing or specific use cases.
  • Highlighting: Use the highlight option in $search to show snippets of matched text.

Conclusion #

Implementing full-text search in Laravel with MongoDB Atlas Search elevates your application's search capabilities from basic filtering to intelligent, relevancy-driven discovery. By understanding and leveraging BM25 indexing and field weighting, you gain precise control over how your search results are ranked, ensuring your users always find what they're looking for efficiently. Experiment with different index configurations and query structures to discover the optimal relevancy for your specific application needs.

FAQs

What is BM25 in full-text search and how does it affect relevancy?
BM25 (Best Match 25) is a ranking function used by search engines to estimate the relevance of documents to a given search query. It calculates relevancy based on factors like how often a search term appears in a document (term frequency), how rare the term is across all documents (inverse document frequency), and the length of the document. A higher BM25 score indicates greater relevancy.
How does field weighting improve search relevancy in MongoDB Atlas Search?
Field weighting allows you to assign different levels of importance to various fields within your documents. By giving a higher 'weight' to a field (e.g., 'name' over 'description'), matches found in that field will contribute more significantly to the overall relevancy score. This helps tune search results to prioritize information from more critical fields, making the search more relevant to user intent.
Do I need MongoDB Atlas to use full-text search with Laravel and MongoDB?
Yes, for robust and fully-featured full-text search capabilities with MongoDB in Laravel, you will need MongoDB Atlas. MongoDB Atlas Search is a cloud-native, managed service built directly into MongoDB Atlas, leveraging Apache Lucene for advanced search features like BM25, field weighting, fuzzy search, and more. While you could technically run a self-hosted MongoDB instance, integrating a separate search engine like Elasticsearch or Solr would be a much more complex endeavor than using Atlas Search.

Want more content like this?

Explore more tutorials in the Laravel section.

Explore Laravel

You might also like