Mongoose: Got "text index required for $text query" when using text search in version 4.3.7

Created on 30 Jan 2016  路  6Comments  路  Source: Automattic/mongoose

Schema:

var schema = exports.Schema = Schema({
    phone: {type: String, unique: true, index: true},
    registered: Boolean,
    username: { type: String, text: true }, // this one has text index.
    password: String,
    avatar: String,
    friends: [ {
        _id: {type: String, unique: true},
        user: { type: Schema.Types.ObjectId, ref: Colle.User },
        nickname: String
    } ],
    tasks: [ { type: String, ref: Colle.Task } ],
    outbox: [ { type: String, ref: Colle.Task } ],
    notes: [ { type: String, ref: Colle.Note } ],
    createdAt: {type: Date, default: Date.now},
    updatedAt: {type: Date, default: Date.now}
});

schema.statics.searchByName = co.wrap(function*(name, page) {
    return yield this.find(
            {$text: {$search: name}},
            {score: {$meta: 'textScore'}}
        ).sort({score: {$meta: 'textScore'}})
        .skip(page*20)
        .limit(20)
        .select('_id username avatar registered createdAt')
        .exec();
});

Add got this error while searchByName is called:

Error: (MongoError) text index required for $text query
    at Function.MongoError.create (/Users/Linkeo/Project/todo/node_modules/mongodb-core/lib/error.js:31:11)
    at queryCallback (/Users/Linkeo/Project/todo/node_modules/mongodb-core/lib/cursor.js:281:36)
    at Callbacks.emit (/Users/Linkeo/Project/todo/node_modules/mongodb-core/lib/topologies/server.js:95:3)
    at null.messageHandler (/Users/Linkeo/Project/todo/node_modules/mongodb-core/lib/topologies/server.js:249:23)
    at Socket.<anonymous> (/Users/Linkeo/Project/todo/node_modules/mongodb-core/lib/connection/connection.js:265:22)
    at emitOne (events.js:77:13)
    at Socket.emit (events.js:169:7)
    at readableAddChunk (_stream_readable.js:146:16)
    at Socket.Readable.push (_stream_readable.js:110:10)
    at TCP.onread (net.js:523:20)

P.S.:

  1. I'm using node.js 5.4.0, mongoldb 3.2.0 and mongoose 4.3.7
  2. I can find out this index in MongoDB shell:
$ mongo
MongoDB shell version: 3.2.0
connecting to: test
> db.users.getIndexes()
...
    {
        "v" : 1,
        "key" : {
            "username" : 1
        },
        "name" : "username_1",
        "ns" : "test.users",
        "text" : true,
        "background" : true
    },
...

Most helpful comment

Use schema.index({ ALB_TITLE: 'text', ART_NAME: 'text', SNG_TITLE: 'text' }) instead of text: true. Also, please turn on the emitIndexErrors option: http://mongoosejs.com/docs/guide.html#emitIndexErrors to avoid errors like this.

All 6 comments

@linkeo how did you create that index? AFAIK a text index should look like this:

{
        "v" : 1,
        "key" : {
            "_fts" : "text",
            "_ftsx" : 1
        },
        "name" : "data.name_text",
        "ns" : "test.venues",
        "background" : true,
        "weights" : {
            "data.name" : 1
        },
        "default_language" : "english",
        "language_override" : "language",
        "textIndexVersion" : 2
    }

As I was written, just add text: true into the name field in the schema.

var schema = exports.Schema = Schema({
    ...
    username: { type: String, text: true }, // <-- this one 
    ...
});
var model = mongoose.model('user', schema);

This was the whole output of db.users.getIndexes():

[
    {
        "v" : 1,
        "key" : {
            "_id" : 1
        },
        "name" : "_id_",
        "ns" : "test.users"
    },
    {
        "v" : 1,
        "unique" : true,
        "key" : {
            "phone" : 1
        },
        "name" : "phone_1",
        "ns" : "test.users",
        "background" : true
    },
    {
        "v" : 1,
        "key" : {
            "username" : 1
        },
        "name" : "username_1",
        "ns" : "test.users",
        "text" : true,
        "background" : true
    }
]

After that, I solve this problem with schema.index({username: 'text'});, and this is the indexes now:

[
    {
        "v" : 1,
        "key" : {
            "_id" : 1
        },
        "name" : "_id_",
        "ns" : "test.users"
    },
    {
        "v" : 1,
        "unique" : true,
        "key" : {
            "phone" : 1
        },
        "name" : "phone_1",
        "ns" : "test.users",
        "background" : true
    },
    {
        "v" : 1,
        "key" : {
            "_fts" : "text",
            "_ftsx" : 1
        },
        "name" : "username_text",
        "ns" : "test.users",
        "background" : true,
        "weights" : {
            "username" : 1
        },
        "default_language" : "english",
        "language_override" : "language",
        "textIndexVersion" : 3
    }
]

The same as yours. But I think text: true written in the schema should also work, right?

Yeah it should work in theory. That looks like a bug. Use the schema.index() workaround for now.

I had this problem in nodejs driver of mongoDB.
It was caused by using:
key" : {
"username" : 1
},
Should be
key" : {
"username" : "text'
},
Just use {username: "text"} when creating the the index
collection.createIndex({ "username" : text });
If you use collection.createIndex({ "username" : 1 }) in the shell,, you get the error message of
"text index required for $text query"
If done in the .js file, it just does not work.

hello. i have a text search on song title and artist name and album name. so
my schema v2 look like this:

`let songSchema = new Schema({

SNG_ID:     {type: String, required: true, unique: true, index: true},

ALB_ID:     {type: String, required: true, unique: false, index: true},

ALB_TITLE:  {type: String, required: true, unique: false, index: true, text: true},

ART_NAME:     {type: String, required: true, unique: false, index: true, text: true},

SNG_TITLE: {type: String, required: false, unique: false, index: false, text: true},

...
});
`
i compile/run my code (Songs.find({})
then
db.songs.getIndexes()

as you can see the fts only apears for ALB_TITLE

"_fts" : "text",

` {
"v" : 1,
"key" : {
"_fts" : "text",
"_ftsx" : 1
},
"name" : "ALB_TITLE_text",
"ns" : "db_name.songs",
"background" : true,
"weights" : {
"ALB_TITLE" : 1
},
"default_language" : "english",
"language_override" : "language",
"textIndexVersion" : 2
}

{
    "v" : 1,
    "key" : {
        "SNG_TITLE" : 1
    },
    "name" : "SNG_TITLE_1",
    "ns" : "db_name.songs",
    "background" : true
}`

You may ask what i am trying to do: given a search string "ABBA Give me" whant to search that text against SNG_TITLE&ART_NAME&ALB_TITLE

Use schema.index({ ALB_TITLE: 'text', ART_NAME: 'text', SNG_TITLE: 'text' }) instead of text: true. Also, please turn on the emitIndexErrors option: http://mongoosejs.com/docs/guide.html#emitIndexErrors to avoid errors like this.

Was this page helpful?
0 / 5 - 0 ratings