Bdyce
Bdyce

Reputation: 332

Mongoose not creating text indexes for multiple fields

I have a basic mongoose schema that requires me to create a text index on two of its fields: name & description.

Here are my mongoose connection options:

mongoose.set('useFindAndModify', false);
mongoose.set('useCreateIndex', true);
mongoose.set('useNewUrlParser', true);

const mongoOptions = {
  useNewUrlParser: true,
  autoIndex: false,
  reconnectTries: Number.MAX_VALUE,
  reconnectInterval: 500,
  poolSize: 10,
  bufferMaxEntries: 0
};

mongoose.connect(MONGOURI, mongoOptions);

Here is my schema:

const ASchema = new mongoose.Schema({
  name: {type: String, text: true, index: true, required: true, maxlength: [100, 'Name must be less than 100 characters']},
  description: {type: String, text: true, index: true, required: true, maxlength: [500, 'Description must be less than 500 characters']},
  meta: {tags: [String]}
});

ASchema.options.autoIndex = true;

ASchema.index({
  name: 'text',
  description: 'text',
}, {
  weights: {
    name: 5,
    description: 3,
  },
});

var A = mongoose.model("AModel", ASchema);

module.exports = A;

For some reason with the query, I create with:

app.post('/search', (req, res, next) => {
  let query = req.query.q
  console.log(query);
  A.find({
    $text: { $search: query }
  }, { score: { $meta: "textScore" } }
  ).sort( { score: { $meta: "textScore" } } )
  .then(q => {
    console.log(q); res.send(q)
  })
  .catch(next)
});

I will only ever get the results if my query string is within the name field. Yet when I enter a sentence or word ONLY present in the description I am returned an empty ARRAY.

calling db.amodels.getIndexes() on my mongo shell returns the following:

[
        {
                "v" : 2,
                "key" : {
                        "_id" : 1
                },
                "name" : "_id_",
                "ns" : "adatabase.amodels"
        },
        {
                "v" : 2,
                "key" : {
                        "_fts" : "text",
                        "_ftsx" : 1
                },
                "name" : "name_text",
                "ns" : "adatabase.amodels",
                "background" : true,
                "weights" : {
                        "name" : 1
                },
                "default_language" : "english",
                "language_override" : "language",
                "textIndexVersion" : 3
        }
]

I can see from this, as well as my mlab instance, that my compound index has not been created, nor has the proper weighting been assigned.

calling db.amodels.ensureIndex({"description": "text"})

returns a IndexOptionsConflict

{
        "operationTime" : Timestamp(1565476058, 1),
        "ok" : 0,
        "errmsg" : "Index: { v: 2, key: { _fts: \"text\", _ftsx: 1 }, name: \"description_text\", ns: \"adatabase.amodels\", weights: { description: 1 }, default_language: \"english\", language_override: \"language\", textIndexVersion: 3 } already exists with different options: { v: 2, key: { _fts: \"text\", _ftsx: 1 }, name: \"name_text\", ns: \"adatabase.amodels\", background: true, weights: { name: 1 }, default_language: \"english\", language_override: \"language\", textIndexVersion: 3 }",
        "code" : 85,
        "codeName" : "IndexOptionsConflict",
        "$clusterTime" : {
                "clusterTime" : Timestamp(1565476058, 1),
                "signature" : {
                        "hash" : BinData(0,"FMoSr4UQZWqocfrRTFvGoa62TsY="),
                        "keyId" : NumberLong("6723301754588364801")
                }
        }
}

Have I messed up somewhere simply? I sure do hope so.

Upvotes: 2

Views: 3328

Answers (1)

whoami - fakeFaceTrueSoul
whoami - fakeFaceTrueSoul

Reputation: 17915

In mongoDB, you cannot create two text indexes i.e; two Single Field text indexes on two different fields of a collection. If really need to create, all you can do is to drop existing one (if it's ok) & create a new compound index with all necessary text fields !! Below is for shell operation or as you already have compound index in schema, you can run your code.

Do something like this :

db.amodels.createIndex(
   {
     name: "text",
     description: "text"
   }
 )

With weights (Optional) :

db.amodels.createIndex(
    {
        name: "text",
        description: "text"
    },
    {
        weights: {
            name: 5,
            description: 3
        },
        name: "name_description"
    }
)

Note : Regd. your creation of indexes - You can start using createIndex as ensureIndex is deprecated ensureIndex to createIndex

Please check this for reference :

MongoDB Text Indexes

Upvotes: 3

Related Questions