猫鼬文字搜索未返回任何结果

时间:2019-11-21 00:42:38

标签: javascript node.js mongodb typescript mongoose

我正在为我的应用程序使用Mongoose 5.7.8,但文本搜索未返回任何结果。

这是一个模式/模型:

import mongoose, { Document, Schema } from 'mongoose';
import { Moment } from 'moment';
import { IUser } from './IUser.model';
import mongooseMoment from 'mongoose-moment';

mongooseMoment(mongoose);

export interface IProfile extends Document {
  given_name: string;
  family_name: string;
  nickname: string;
  name?: string;
  picture?: string;
  locale?: string;
  updated_at?: Moment;
  email?: string;
  email_verified?: string;
  sub: string;
  user: IUser['_id'];

  bySub(sub: string): any;
}

export const ProfileSchema: Schema = new Schema({
  given_name: {type: Schema.Types.String, required: true},
  family_name: {type: Schema.Types.String, required: true},
  nickname: {type: Schema.Types.String, required: true},
  name: {type: Schema.Types.String, required: false, unique: false},
  picture: {type: Schema.Types.String, required: false, unique: false},
  locale: {type: Schema.Types.String, required: false, unique: false},
  updated_at: {type: 'Moment', required: false, unique: false},
  email: {type: Schema.Types.String, required: false, unique: false},
  email_verified: {type: Schema.Types.String, required: false, unique: false},
  sub: {type: Schema.Types.String, required: true, unique: true, index: true},
  user: {type: Schema.Types.ObjectId, ref: 'User'}
});

ProfileSchema.query.bySub = function (sub: string) {
  return this.where({sub});
};

ProfileSchema.index({'given_name': 'text', 'family_name': 'text', 'nickname': 'text'});

export default mongoose.model<IProfile>('Profile', ProfileSchema);

这是一个正在搜索配置文件的控制器:

const criteria = 'a';

const profiles: IProfile[] = await Profile.find(
  {
    $text:
      {
        $search: criteria,
      }
  }
);

不幸的是,即使有符合条件的文档,profiles始终为空。我可能做错了什么?

1 个答案:

答案 0 :(得分:1)

围绕创建索引似乎存在一些一致性问题。您可能在创建索引之前之前触发查询,甚至可能尚未创建索引。测试时,以下内容适用于我在本地开发中的工作。

我建议您直接在Mongodb中创建索引,并完全使用连接字符串中的autoIndex: false从Moongose中删除索引。

mongoose.connect(`mongodb://localhost/tests`, {useNewUrlParser: true, useUnifiedTopology: true, autoIndex: false});

但是对于开发人员并帮助您回答问题:

定义索引,然后运行await Profile.ensureIndexes();,它检查模型的索引是否存在。如果需要,它将运行createIndex

查看内联评论:

// define schema
let schema = new Schema(
    {
        id: {
            type: Number,
            required: true
        },
        name: {
            type: String,
            required: true
        },
        content: {
            type: String,
            required: true
        }
    },
    {
        versionKey: false,
        timestamps: false,
        autoIndex: false // set false as this create significant load on your production database
    }
);

// define the text index
schema.index({ content: 'text', name: 'text' }, {name: 'my text index'});

// initialize the model
const Profile = mongoose.model('profiles', schema);

// insert some data
const profile = await Profile.create({
    id: 1,
    name: 'Darth "The Sith Lord" Vader',
    content: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.'
});

// event to notify us when indexes are created
Profile.on('index', (err) => {
    if (err) {
        return console.error(err);
    }

    console.info(`index created`);
});

// ensure we have the indexes, this will use createIndex in the background
await Profile.ensureIndexes();

// now run the query using the index
const result = await Profile.find({
        $text:
            {
                $search: 'consectetur adipiscing',
            }
    },
    {
        _id: 0,
        name: 1
    }
);

console.info(result);
[ { name: 'Darth "The Sith Lord" Vader' } ]