$search autocomplete returns an empty array

Dear members

I’m a mongodb (and backend) beginner and try to create an autocomplete search. Unfortunately, I always get back an empty array in my console. In another thread the reason was that the user had renamed the index. This is not the case with me.

Here’s my code:

//controller for search query with autocomplete function (get request)

exports.search = async (req, res) => {
    try {
        //await aggregated query on mongodb
        const searchRequest = await Product.aggregate([
            {
                '$search': {
                    'autocomplete': {
                        'query': `${req.query.productName}`,
                        'path': 'productName',
                        'fuzzy': {
                            'maxEdits': 2,
                            'prefixLength': 3
                        }
                    }

                }
            }]).toArray();

        //send result of search query from mongodb
        res.send(searchRequest);
    }
    catch (error) {
...
};

This is my index:

{
  "mappings": {
    "dynamic": true,
    "fields": {
      "productName": [
        {
          "dynamic": true,
          "type": "document"
        },
        {
          "foldDiacritics": false,
          "maxGrams": 7,
          "minGrams": 3,
          "type": "autocomplete"
        }
      ]
    }
  }

I have already tried different variants (e.g. with or without quotes etc.), but I just can’t find a solution. Maybe someone has an idea? Thanks in advance for the help.

@dj_ch Welcome to the community forum. Beginners totally welcome!

I don’t know exactly what’s going on yet.

Could you try three steps for me?

  1. Paste a sample document from your collection so I can take a look.

  2. Remove fuzzy to isolate this issue.

  3. Change your index definition for productName to this:

{
         "foldDiacritics": false,
         "maxGrams": 7,
         "minGrams": 3,
         "type": "autocomplete"
       }

In other words, eliminate the document type definition for productName to isolate the issue. Looking forward to getting autocomplete to work for you.

Dear Marcus,
thank you so much for your quick answer! :slightly_smiling_face:

Here’s a sample document from my collection:

1.	_id: 60678678756c434034a2f562
2.	productName: "Dragon Fruit"
3.	productCategory: "Früchte & Gemüse"
4.	lastModificationDate: 2021-04-02T21:02:48.427+00:00
5.	__v: 0

I’ve removed fuzzy, it now looks this way:

exports.search = async (req, res) => {

    try {
        const searchRequest = await Product.aggregate([
            {
                $search: {
                    'autocomplete': {
                        'query': `${req.query.productName}`,
                        'path': 'productName',
                        /*fuzzy: {
                            maxEdits: 2
                            prefixLength: 3
                        }*/
                    }
               }
           }])//.toArray()

        //send result of search query from mongodb
        res.send(searchRequest);

Further I’ve changed the JSON of my index accordingly:

{
  "mappings": {
    "dynamic": true,
    "fields": {
      "productName": [
        {
          "foldDiacritics": false,
          "maxGrams": 7,
          "minGrams": 3,
          "type": "autocomplete"
        }
      ]
    }
  }
}

Unfortunately I still get the same result (empty array). Btw I commented out the toArray() because I got an error that toArray() is not a function.

Can you try to build this query in the aggregation pipeline builder in Atlas to confirm it is not your application code:

  1. navigate to Collections > Aggregations > select the $search operator
  2. add the query (don’t forget the search index name because it is required if it is not default):
'$search': {
                    'autocomplete': {
                        'query': 'Drago',
                        'path': 'productName'
                    }

                }

This will help us to isolate this issue. See the parenthetical in step 2 also, in case you should have an index name in your original query.

Hi!

I just want to emphasize what Marcus says above for step 2. Unless your index is named “default,” make sure to include it in your $search stage.

So in your code listed above, it would look like this:

try {
    //await aggregated query on mongodb
    const searchRequest = await Product.aggregate([
        {
            '$search': {
                'index': "<index name>", // optional, defaults to "default"
                'autocomplete': {
                    'query': `${req.query.productName}`,
                    'path': 'productName',
                    'fuzzy': {
                        'maxEdits': 2,
                        'prefixLength': 3
                    }
                }

            }
        }]).toArray();

Hope this helps.

Karen

Dear Marcus and Karen
Thanks for the tip with the aggregation pipeline builder! I have now created a new index with a specific name and tested everything. I copied out the code from the aggregation pipeline builder and now it works! I honestly still do not know where the error was exactly. But I am very happy and thankful that I can use autocomplete now. Thank you very much for the help!
Daniela

2 Likes