在运行我的测试时,我收到一个错误,指出我还没有在标题字段上设置文本索引,但在运行我的应用程序时,文本搜索可以很好地使用相同的模型,并且不会抛出错误。
$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);
Run Code Online (Sandbox Code Playgroud)
我正在使用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);
});
Run Code Online (Sandbox Code Playgroud)
这是 ava 的完整输出,因为您可以看到 title 的索引不是使用 '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.
Run Code Online (Sandbox Code Playgroud)
您应该确保索引是在“前台”中创建的,因为“后台”创建是默认的。
Torrent.index({
title: 'text'
},{ "background": false });
Run Code Online (Sandbox Code Playgroud)
至少对于您的测试,否则有可能在创建索引之前运行查询。设置{ background: false }确保索引在其他操作可以运行之前就已经存在。这与MongoDB的默认行为相反,因此需要进行显式设置。
在生产环境中,通常最好通过其他方式部署索引。“前台”创建也会导致较小的索引大小,但当然会“阻止”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();
});
});
});
Run Code Online (Sandbox Code Playgroud)
作为替代方法,自动关闭猫鼬自动索引功能并手动设置,然后通过.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();
});
});
});
});
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2400 次 |
| 最近记录: |