2017-06-10 49 views
0

當運行我的測試時,我收到一個錯誤,說明我沒有在標題字段上設置文本索引,但運行我的應用程序時文本搜索工作正常模型,不要拋出錯誤。我使用ava用於測試和這裏$文本查詢(沒有這樣的集合「測試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); 

是我測試的情況。

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全輸出中,你可以看到標題索引不會與「文」或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

你是否將你的集合放入測試中?在創建索引之前可能會有查詢開始執行的情況。在'mongoose.connect()'被調用之前設置'mongoose.set(「debug」,true)''看到了什麼? –

+0

所有測試完成後,系列都會丟失。我完全忘記了貓鼬的調試模式。我會檢查並回來。 –

+0

經過一些測試後,它看起來像mongoose添加了'background:true'來創建索引,這意味着索引是在測試完成後創建的。 –

回答

2

您應該確保該指數是在「前臺」創建自「背景」的創作是默認的。

Torrent.index({ 
    title: 'text' 
},{ "background": false }); 

至少對於您的測試,否則可能會在創建索引之前運行查詢。設置{ background: false }可確保索引在其他操作可以運行之前存在。這與MongoDB的default behavior相反,所以它需要是一個明確的設置。

在生產環境中,通常最好是通過其他方式部署索引。同樣,「前景」的創造導致索引規模較小,當然還有「塊」IO,但通常在製作中至少要做一次。

引文從documentation

默認情況下,建立的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(); 
    }); 
    }); 
}); 

作爲另一種方法,關閉貓鼬自動變址自動功能和手動設置,然後手動調用創建經由.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(); 
     }); 
    }); 
    }); 
}); 
+0

看起來不像這樣,我仍然遇到同樣的問題,並且沒有設置索引的貓鼬輸出。 –

+1

@AlexisTyler它適用於我。無論如何,前臺索引創建應該阻止IO。文檔中有更多有關前景索引創建的註釋。我現在只是在挖一些東西。 –

+0

@AlexisTyler添加了一個至少重現的最小情況。在查詢可以運行之前,這將始終創建索引 –