skip to Main Content

I’m getting an empty array when using $search in mongoose.

Schema

const mongoose = require('mongoose');

const studentSchema = new mongoose.Schema({
  name: { type: String },
});

studentSchema.index({ name: 'text' });

const Student = mongoose.model('Student', studentSchema);
module.exports = Student;

$search

const Student = require('../models/Student.Model');
(async () => {
    const result = await Student.aggregate([
           {
        $search: {
          index: 'default',
          compound: {
            must: [
              {
                text: {
                  query: 'Lee',
                  path: 'name',
                  fuzzy: {
                     maxEdits: 1,
                  },
                },
              },
            ],
          },
        },
      },
    ]);

})();

This gives me an empty array. So I tried another syntax.

const result = await Student.aggregate().search({
      index: 'default',
      compound: {
        must: [
          {
            text: {
              query: 'Lee',
              path: 'name',
              fuzzy: {
                maxEdits: 1,
              },
            },
          },
        ],
      },
    });

That also gave me an empty array.

To test whether the model was working I used find and filter, and could see similar results I’d expect to see with $search.

let result2 = await Student.find({});

result2 = result2.filter((p) => p.name.includes('Lee'));
    

result2 had two documents

result2:  [
  { _id: 625f70ac90e916620045cab5, name: 'Brian Lee', __v: 0 },
  { _id: 625f70e39660b486c82b2011, name: 'Lee Cohen', __v: 0 }
]

Update: find and $text also give me the above correct results, but I want to implement a fuzzy search and I don’t think you can with find and $text`:

const resultsShort = await Student.find({ $text: { $search: 'Lee' } });

Why isn’t $search returning these two documents?

2

Answers


  1. Chosen as BEST ANSWER

    This creates a $text index not an Atlas Search index:

    studentSchema.index({ name: 'text' });

    The above can be removed.

    You can't create an Atlas Search index on a mongoose schema, it has to be set on the Atlas site or the CLI.

    To create an Atlas Search index, go to your database on cloud.mongodb.com ->Search-->Create Search Index-->JSON Editor-->Next-->pick your collection--> set the index name. here it would be 'default'

    Then set the index:

    { 
      "mappings": {
        "dynamic":false,
        "fields":{
        "name":{
        "analyzer":"lucene.standard",
        "type":"string"
        }
      }
    }
    

    Then this code works.

    const result = await Student.aggregate().search({
          index: 'default',
          compound: {
            must: [
              {
                text: {
                  query: 'Lee',
                  path: 'name',
                  fuzzy: {
                    maxEdits: 1,
                  },
                },
              },
            ],
          },
        });
        ```
    

  2. Use $regex

    db.collection.find({
      name: {
        $regex: "Lee"
      }
    })
    

    mongoplayground


    createIndex

    db.collection.createIndex({name:"text"})
    

    text search

    db.collection.find({$text: {$search: "Lee"}})
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search