mongoDB autocomplete returns empty array

I am using mongodb’s sample movie database (https://docs.atlas.mongodb.com/sample-data/sample-mflix#std-label-sample-mflix) to experiment with mongodb’s autocomplete functionality. The search always returns an empty array. I am using Atlas on the free tier.

I have set up a Search Index as follows:

{
  "mappings": {
    "dynamic": false,
    "fields": {
      "title": [
        {
          "minGrams": 3,
          "tokenization": "edgeGram",
          "type": "autocomplete"
        }
      ]
    }
  }
}

The model and the search query are setup as follows:

// Creating the Movies model
const Movies = mongoose.model("Movies", new mongoose.Schema({}), "movies");

// Impplementing autocomplete search
app.get("/search", async (req, res) => {
  try {
    let result = await Movies.aggregate([
      {
        $search: {
          autocomplete: {
            path: "title",
            query: req.query.title,
            fuzzy: {
              maxEdits: 2,
              prefixLength: 3,
            },
          },
        },
      },
    ]);
    res.status(200).json({
      status: "success",
      results: result.length,
      data: { result },
    });
  } catch (error) {
    console.log(error);
  }
});

I am using postman to run test queries and a sample query is: 127.0.0.1:3030/search?title=black

The model can be queried using .find(), for example, and returns the full collection of documents.

Any and all help is greatly appreciated.

Hi @Eest_Said,

I have exactly the same problem. .find() works fine with and without params and .aggregate() works with a “$match” stage, but when using autocomplete it only returns an empty array.

Did you find any solution for this issue?

@LudiG. Apologies for the delay in responding. Unfortunately I did not find a solution to utilise mongodb’s autocomplete feature. I ended up using another approach to address the issue I was facing. What are you trying to use the feature for? Best of luck.

@Eest_Said no worries!
I am still trying to figure out the error, but couldn’t track it down yet. At first I thought it’s an issue of mongoose returning plain javascript instead of mongoose objects when using aggregate (mongoose documentation), but it works fine with a $match stage so this shouldn’t be the problem.

I want to use it for suggestions in a text search. It’s pretty much a straight forward application scenario for autocomplete. What did you use instead?

@Eest_Said I finally happened to solve it!!

The issue was that I used a different index name than “default” when creating the index and the autocomplete documentation (autocomplete) didn’t mention that this name has to be specified if it deviates from “default”. However I found a small note here in step 8, where it says that you need to specify the index name in the parameters of $search.

Hence, when specifying the index like this it worked:

         {
              "$search": {
                    "index": "<your-index-name>",
                    "autocomplete": {
                        "query": `${req.query.name}`,
                        "path": "name"
                    }
                }
            }
1 Like

@LudiG wonderful! I can’t wait to test this out.

So I used a simple regex to query the DB. My requirement is to allow searching of consecutive values. For example, the user might be searching for all entries that contain apples AND bananas so a search for ‘apples,b’ should return all entries that contain apples AND all entries starting with ‘b’. Because I use an array to store the progressive search, the key line of code to capture the current search value is …

newQueryArray.splice(-1, 1, new RegExp(^${currentQueryString}));

Then the DB is queried with a .find() using the $all operator.

let result = await FruitTest.find({

      tags: {

        // Filter must inclupde ALL array items.

        // Final array item is regex - see newQueryArray above.

        $all: newQueryArray,

      },

    });

Thanks again @LudiG and I will try an implement what you have suggested over the weekend.

1 Like