2017-07-19 9 views
1

私は約100万のドキュメント(主に映画)のコレクションを持っており、フィールドにテキストインデックスを作成しました。ほぼすべての検索ですべて正常に動作します:20ms未満で結果が得られます。例外は非常に頻繁な用語の1つの検索で、3000ミリ秒まで続くことができます!例えば 、MongoDB:非常に頻繁な用語を検索するときにスローテキスト検索

私はコレクション(唯一の40の文書がそれを持っている)私は「映画」(750個の000の文書がそれを持っている)を検索する場合、それは1msの

続く中で「パルプ」を検索すると

は、それが続きます3000ms。 要求をプロファイリングするとき、explain( 'executionStats')はすべての映画のドキュメントがスキャンされたことを示します。私は多くのインデックス作成、ソート+制限とヒントを試しましたが、75万の文書はすべてスキャンされていますが、結果はまだまだ遅いです...

データベース内の非常に頻繁な用語をすばやく検索できる戦略はありますか?

+0

これは正常な動作です、それについて考えます。すべての単語がインデックスに登録されるため、テキストインデックスは実際のコレクションよりもはるかに大きくなります。コレクション全体よりも大きいインデックスの一部を検索すると、mongoDBは実際のコレクション自体をスキャンします。インデックスを強制的に使用することができれば、それはさらに遅くなります。結果を速くするには、結果を制限することができますか? –

+0

私は制限しようとしましたが、ソートされた出力が必要なので、すべてのドキュメントはまだスキャンされています...論理的に。 – Eric

答えて

0

私はこのような何かをコーディングすることにより、自分のストップワードリストを行うに終了:

import pymongo 
from bson.code import Code 

# NB max occurences of a word in a collection after what it is considerated as a stop word. 
NB_MAX_COUNT = 20000 
STOP_WORDS_FILE = 'stop_words.py' 

db = connection to the database... 

mapfn = Code("""function() { 
    var words = this.field_that_is_text_indexed; 
    if (words) { 
     // quick lowercase to normalize per your requirements 
     words = words.toLowerCase().split(/[ \/]/); 
     for (var i = words.length - 1; i >= 0; i--) { 
      // might want to remove punctuation, etc. here 
      if (words[i]) {  // make sure there's something 
       emit(words[i], 1); // store a 1 for each word 
      } 
     } 
    } 
};""") 

reducefn = Code("""function(key, values) { 
    var count = 0; 
    values.forEach(function(v) { 
     count +=v; 
    }); 
    return count; 
};""") 

with open(STOP_WORDS_FILE,'w') as fh: 
    fh.write('# -*- coding: utf-8 -*-\n' 
      'stop_words = [\n') 

    result = db.mycollection.map_reduce(mapfn,reducefn,'words_count') 
    for doc in result.find({'value':{'$gt':NB_MAX_COUNT}}): 
     fh.write("'%s',\n" % doc['_id']) 

    fh.write(']\n') 
関連する問題