运行我的测试时,我收到一条错误消息,指出我没有在标题字段上设置文本索引,但在运行我的应用程序文本搜索时,使用相同的模型可以正常搜索并且不会抛出错误。
$ text查询所需的文本索引(没有这样的集合' test-db.torrents')
import mongoose from 'mongoose';
import Category from './category';
const Schema = mongoose.Schema;
const Torrent = new Schema({
title: {
type: String
},
category: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Category',
required: true,
index: true
},
size: Number,
details: [
{
type: String
}
],
swarm: {
seeders: Number,
leechers: Number
},
lastmod: {
type: Date,
default: Date.now()
},
imported: {
type: Date,
default: Date.now()
},
infoHash: {
type: String,
unique: true,
index: true
}
});
Torrent.index({
title: 'text'
}, {
background: false
});
export default mongoose.model('Torrent', Torrent);
我使用ava进行测试,这是我的测试用例。
import mongoose from 'mongoose';
import request from 'supertest';
import test from 'ava';
import {makeApp} from '../helpers';
test.before(() => {
mongoose.Promise = Promise;
mongoose.connect('mongodb://localhost:27017/astro-test-db');
});
test.after.always(() => {
mongoose.connection.db.dropDatabase(() => {
mongoose.disconnect();
});
});
// Should return [] since HL3 doesn't exist.
test('should return no search results', async t => {
const app = makeApp();
const res = await request(app).get(`/api/search?q=HL3`);
t.is(res.status, 200);
t.is(res.body.error, {});
t.is(res.body.torrents.length, 0);
});
这里是ava的完整输出,因为你可以看到标题的索引没有用' text'来创建。或background: false
。
➜ astro git:(develop) ✗ yarn ava test/routes/search.js -- --verbose
yarn ava v0.24.6
$ "/Users/xo/code/astro/node_modules/.bin/ava" test/routes/search.js --verbose
Mongoose: categories.ensureIndex({ title: 1 }, { unique: true, background: true })
Mongoose: torrents.ensureIndex({ category: 1 }, { background: true })
Mongoose: torrents.count({}, {})
Mongoose: categories.ensureIndex({ slug: 1 }, { unique: true, background: true })
Mongoose: torrents.find({ '$text': { '$search': 'x' } }, { limit: 100, sort: { score: { '$meta': 'textScore' }, 'swarm.seeders': -1 }, fields: { score: { '$meta': 'textScore' } } })
✖ should return no search results
1 test failed [13:59:07]
should return no search results
/Users/xo/code/astro/test/routes/search.js:24
23: t.is(res.status, 200);
24: t.is(res.body.error, {});
25: t.is(res.body.torrents.length, 0);
Difference:
- Object {
- code: 27,
- codeName: "IndexNotFound",
- errmsg: "text index required for $text query (no such collection \'astro-test-db.torrents\')",
- message: "text index required for $text query (no such collection \'astro-test-db.torrents\')",
- name: "MongoError",
- ok: 0,
- }
+ Object {}
_callee$ (test/routes/search.js:24:7)
tryCatch (node_modules/regenerator-runtime/runtime.js:65:40)
Generator.invoke [as _invoke] (node_modules/regenerator-runtime/runtime.js:303:22)
Generator.prototype.(anonymous function) [as next] (node_modules/regenerator-runtime/runtime.js:117:21)
step (test/routes/search.js:19:191)
error Command failed with exit code 1.
答案 0 :(得分:4)
您应该确保索引是在"前景"中创建的。自"背景"创建是默认的。
Torrent.index({
title: 'text'
},{ "background": false });
至少对于您的测试,否则查询可能会在创建索引之前运行。设置{ background: false }
可确保在其他操作可以运行之前索引存在。这与MongoDB的default behavior相反,因此它需要是一个明确的设置。
在生产环境中,通常最好通过其他方式部署索引。还有"前景"创建导致较小的索引大小,但当然"块" IO,但在生产中至少一次这样做仍然更好。
的引文默认情况下,MongoDB在前台构建索引,这会在索引构建时阻止对数据库的所有读写操作。此外,在前台索引构建期间,不会对所有数据库(例如listDatabases)执行读取或写入锁定的操作。
这意味着发生这种情况时不会发生读取或写入操作。因此,当在"前景"中创建索引时,无法插入数据并且无法运行查询。创作模式。
就尺寸而言,距离引文相同的页面稍远一点:
后台索引构建需要更长时间才能完成,并且导致索引最初比前台中构建的索引更大或更紧凑。随着时间的推移,在后台构建的索引的紧凑性将接近前景构建的索引。
因此,您可以在后台创建索引"随着时间的推移" 在生产环境中缩小到更紧凑的尺寸。但是对于测试和开发目的,您的默认值应该始终是在"前景"为了不被时间问题所困扰。
作为最小测试用例:
var mongoose = require('mongoose'),
Schema = mongoose.Schema;
mongoose.set('debug', true);
var testSchema = new Schema({
title: { type: String }
});
testSchema.index({
title: 'text'
},{ background: false });
var Test = mongoose.model('Test', testSchema);
mongoose.connect('mongodb://localhost/texttest');
Test.create({ title: 'something here' },function(err,doc) {
Test.find({ "$text": { "$search": "something" } },function(err,doc) {
if (err) throw err;
console.log(doc);
Test.collection.drop(function(err) {
if (err) throw err;
mongoose.disconnect();
});
});
});
作为替代方法,请自动关闭mongooses自动索引功能并手动设置,然后通过.ensureIndexes()
手动调用创建:
var async = require('async'),
mongoose = require('mongoose'),
Schema = mongoose.Schema;
mongoose.set('debug', true);
var testSchema = new Schema({
title: { type: String }
},{ autoIndex: false });
testSchema.index({
title: 'text'
},{ background: false });
var Test = mongoose.model('Test', testSchema);
mongoose.connect('mongodb://localhost/texttest');
// Manually set indexing to on
Test.schema.options.autoIndex = true;
//console.log(Test.schema.options);
Test.ensureIndexes(function(err) {
if (err) throw err;
Test.create({ title: 'something here' },function(err,doc) {
Test.find({ "$text": { "$search": "something" } },function(err,doc) {
if (err) throw err;
console.log(doc);
Test.collection.drop(function(err) {
if (err) throw err;
mongoose.disconnect();
});
});
});
});