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.:
$ 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
},
...
@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.
Most helpful comment
Use
schema.index({ ALB_TITLE: 'text', ART_NAME: 'text', SNG_TITLE: 'text' })
instead oftext: true
. Also, please turn on theemitIndexErrors
option: http://mongoosejs.com/docs/guide.html#emitIndexErrors to avoid errors like this.