Efficiently search in MongoDB by combining $text search with $regex query

Dealing with mongodb has presented me with a challenge: when using $text searches, the match has to be an exact word. For example, searching for 'test' will not find a post containing 'testing123', but using $regex would work. I want to utilize indexes while still allowing partial matches.

I thought of using an $or operator to combine them, but it doesn't seem to be working. Each query by itself within the $or works fine, but together they do not yield any results.

If combining them is not possible, I came across a helpful solution here. However, I prefer the combined $or approach if feasible, though I am open to other suggestions.

const posts = await Post.find({
  name: { $regex: 'foo', $options: 'i' },
  $or: [
    { $text: { $search: text, $caseSensitive: false } },
    { text: { $regex: text, $options: 'i' } },
  ],
});

Answer №1

To search for a substring case insensitively, one approach is to convert the text to lowercase in a separate field and then use $regex search on that new field.


If you have text that you need to search without considering the case:

MongoDB Enterprise ruby-driver-rs:PRIMARY> db.foo.insert({foo:'hello world TESTING123'})
WriteResult({ "nInserted" : 1 })

Step 1: Create another field to store the text in lowercase.

MongoDB Enterprise ruby-driver-rs:PRIMARY> db.foo.insert({foo:'hello world TESTING123',foo_lower:'hello world testing123'})

Step 2: Add an index.

MongoDB Enterprise ruby-driver-rs:PRIMARY> db.foo.createIndex({foo_lower:1})
{
    "createdCollectionAutomatically" : false,
    "numIndexesBefore" : 2,
    "numIndexesAfter" : 3,
    "commitQuorum" : "votingMembers",
    "ok" : 1,
    "$clusterTime" : {
        "clusterTime" : Timestamp(1597711723, 7),
        "signature" : {
            "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
            "keyId" : NumberLong(0)
        }
    },
    "operationTime" : Timestamp(1597711723, 7)
}

Step 3: Search for "testing123" after converting it to lowercase.

Step 4: Utilize $regex for the search.

MongoDB Enterprise ruby-driver-rs:PRIMARY> db.foo.find({foo_lower:{$regex:'testing123'}})
{ "_id" : ObjectId("5f3b2498f885e53d90f30979"), "foo" : "hello world TESTING123", "foo_lower" : "hello world testing123" }
MongoDB Enterprise ruby-driver-rs:PRIMARY> db.foo.find({foo_lower:{$regex:'testing123'}}).explain()
{
    "queryPlanner" : {
        "plannerVersion" : 1,
        "namespace" : "test.foo",
        "indexFilterSet" : false,
        "parsedQuery" : {
            "foo_lower" : {
                "$regex" : "testing123"
            }
        },
        "queryHash" : "0D14CC56",
        "planCacheKey" : "1974A2D4",
        "winningPlan" : {
            "stage" : "FETCH",
            "inputStage" : {
                "stage" : "IXSCAN",
                "filter" : {
                    "foo_lower" : {
                        "$regex" : "testing123"
                    }
                },
                "keyPattern" : {
                    "foo_lower" : 1
                },
                "indexName" : "foo_lower_1",
                "isMultiKey" : false,
                "multiKeyPaths" : {
                    "foo_lower" : [ ]
                },
                "isUnique" : false,
                "isSparse" : false,
                "isPartial" : false,
                "indexVersion" : 2,
                "direction" : "forward",
                "indexBounds" : {
                    "foo_lower" : [
                        "[\"\", {})",
                        "[/testing123/, /testing123/]"
                    ]
                }
            }
        },
        "rejectedPlans" : [ ]
    },
    "serverInfo" : {
        "host" : "serene",
        "port" : 14420,
        "version" : "4.4.0",
        "gitVersion" : "563487e100c4215e2dce98d0af2a6a5a2d67c5cf"
    },
    "ok" : 1,
    "$clusterTime" : {
        "clusterTime" : Timestamp(1597711761, 1),
        "signature" : {
            "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
            "keyId" : NumberLong(0)
        }
    },
    "operationTime" : Timestamp(1597711761, 1)
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

The shader on the background plane takes precedence over all other elements in three.js

I'm struggling to achieve a simple setup in my scene where a plane serves as the background with a shader, and a box is placed on top with a lambert material. Despite my efforts, I can't seem to make both the plane and the box appear together. An ...

I am looking to set an HTML file as the homepage for my Next.js project

Is there a way in next.js to render a normal .html file (index.html) when someone visits my root directory at "https://example.com/"? I have researched and edited my config file as shown below, /** @type {import('next').NextConfig} */ const next ...

Duplicate documents being returned by mongoose pagination

To achieve pagination, I have set up a system where only two documents are returned at a time. This allows me to determine whether there are more documents available to fetch or if the user has reached the last page. The code snippet below is adapted from ...

Methods for dynamically adjusting pixel coordinates in HTML5 Canvas

My latest project involves an innovative HTML5 drawing application that leverages the power of the HTML5 Canvas element. I've successfully implemented code to create stunning sketches on the Canvas. Initially, my Canvas was set at a size of 500px x 5 ...

The drop-down button unexpectedly disappears when using Bootstrap in combination with jQuery autocomplete

I have some javascript code that is structured like: <!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>jQuery UI Autocompl ...

Transforming the format from YYYYMMDD using MomentJS

Currently, I have a date in the format of YY as shown here: 20141229. I am attempting to convert it into Timestamp format. I attempted using moment(date).format('x'), but received an "Invalid date" error. I'm unsure of how to accomplish this ...

Transforming a Blob document into JSON format

I am attempting to convert a blob file into JSON format in order to transmit it via AJAX requests. Despite my efforts with the code below, I have not been successful in achieving this task. When I attempt to parse the JSONified file, I end up with a comp ...

Favicon not appearing on Jekyll website

This is my first time working with Jekyll. I'm currently working on localhost and trying to set a favicon for the website. I generated the image.ico and added the code provided to my head.html file. The image appears in my _site folder, but it's ...

Issue with ng-style not updating correctly

Within my html file, I have implemented the following code to showcase a square game board utilizing ng-style for dynamic updating of the background-color as the program progresses: <div class="row" ng-repeat="col in board"> <div class="c ...

Tips for preserving an HTML dynamic table in a database

I have a challenge where I am generating a dynamic HTML table using javascript. What is the best way to store this dynamic HTML table in a database using CodeIgniter? This is the code snippet for my input form: <table id="tb3" name="tb3"> & ...

403 Forbidden - CSRF Token Not Recognized

I am encountering an issue with Node Express and CSurf - 403 (Forbidden) Invalid csrf token. After reviewing other solutions and attempting all available options, I am still unable to resolve this. The API functions perfectly when tested in Postman. Howe ...

What are the recommended guidelines for organizing files in an NPM package for front-end development?

I am creating an NPM package for the front-end and I'm trying to figure out the optimal file structure. My package consists of a code.js file as well as a code.min.js file. Should these files be located in the root directory, a dist folder, or a src f ...

Dealing with text changes in JQuery inputs: best practices

Although this question has been raised numerous times, a definitive answer remains elusive. My goal is to trigger a process (such as an ajax call) when a user types into an input field. Initially, I attempted to utilize the onchange event, but it failed to ...

"Encountering a 500 internal server error with jQuery and WordPress

I'm having issues implementing ajax into my WordPress project to dynamically load videos based on their post ID. Whenever I click on the video link, a 500 internal server error occurs. I'm sending the post ID through ajax to a PHP script where I ...

A frigid commitment sealed within a software test

I've encountered an unexpected issue while testing a service that returns a standard $q promise. Strangely, none of the promises I test seem to be resolved or rejected (specifically, the handlers from then are not being called even though the code ins ...

Managing repeated calls to a specific get function in nodejs

Utilizing an Ajax call, I am invoking the following GET function every 10 seconds to monitor the status of various URLs. app.get('/getUrl', function(req, res) { var response = {}; var keyArr = []; var urlData ...

Guide to Embedding Content Script into Local Page

Allow me to give you an overview of the current situation; I am in the process of developing a Chrome extension that conducts searches on specific websites, retrieves the results, and then opens a new tab containing a table where all the results are displ ...

I am interested in organizing elements within an array based on a specific field using pymongo

My MongoDB contains a table with the following structure: { "holdng_name":"MCT", "employes":[ {"name":"Koroglu", "number":4}, {"name":"Babek", "number":1}, {"name":"Uzun Hasan", "number":3}, {"name":"Fatali Xan", "number":2} ] } ...

Using the .map method to filter through JSON data

I'm facing some challenges filtering a .json file to exclude private videos on an app related to a YouTube channel. There are certain videos marked as private that I do not want to display within the app. Can someone assist me in properly filtering th ...

Refreshing the Angular directive following a change in the scope variable

Just getting started with Angular and I've encountered a small issue. Within my template for SirroccoListing, I have the following code. Sirrocco is a directive: <h3>All Sirroccos</h3> <div sirrocco ng-repeat="sirrocco in sirroccos" ...