2016-08-26 5 views
6

3.3.11 supports case insensitive index(照合を使用している)を見つけた後、私は4000万レコードのデータベースを再構築しました。代わりに、大文字と小文字を区別しない検索に固有の小文字のフィールドとそのインデックスMongoDBの大文字と小文字を区別しないインデックスが "パフォーマンスの問題で始まる"

私がしたことは、作成時に自分のコレクションの照合をsuggested hereとしてMongoDBに依頼することでした。私は次のように直接クエリを試してみましたが、コレクションロードした後

db.createCollection("users", {collation:{locale:"en",strength:1}}) 

:だから私は、全体のコレクションのケース非感受性を可能にするためにこれをした

db.users.find({full_name:"john doe"}) 

を...と50回の結果と〜10msの中にそれらのリターン。大文字と小文字は区別されません。しかし、私のような何かしてみてください:

db.users.find({full_name:/^john/}) 

...か...

db.users.find({full_name:/^john/i}) 

を...そしてこれは5分以上かかります。私はとても失望していた。 explain()を実行した後、インデックスが使用されているように見えますが、クエリの実行に時間がかかりすぎます。これは、バグや不完全な開発リリースに起因することができますか、私は根本的に何か間違っているのですか?

私は "starts with"正規表現検索を行っているので、クエリは高速でなければなりません。何か案は?

+0

こんにちは!私たちは3.4に移行してあなたの質問を見つけました。問題の原因を見つけましたか?最新の3.3.xで正常に動作していますか?ありがとう.. – Ruben

+1

実際には動作していません。 3.4をインストールし、https://docs.mongodb.com/master/reference/command/setFeatureCompatibilityVersion/#dbcmd.setFeatureCompatibilityVersionでデータベースを3.4にアップグレードし、新しいコレクション(既定の照合、en、強度2)を作成し、11をインポートしました。 (正規表現は/^find/iと似ています) – wpfwannabe

+0

真新しいデータベースと上のすべてのステップがあっても、それは瞬時ではありません。おそらく私のコメントは誤解を招いていたでしょう。それは動作していますが、正規表現では遅いです。完全な単語で検索すると(部分一致ではなく、非常に高速です)。 – wpfwannabe

答えて

1

編集:実行可能な回避策があります。基本的に探している単語が "bob"の場合、$ lt: "boc"(最後の文字を1つ増やします)と$ gte "bob"を検索できます。これはインデックスを使用します。あなたは、私はこのような(その必ずしもバグ自由が、かなり多くの作品を警告)以下の作っ次の関数を使用することができます。

var searchCriteria = {}; 
addStartsWithQuery(searchCriteria, "firstName", "bo"); 
People.find(searchCriteria).then(...); 

//searchCriteria will be 
/* 
{ 
    $and:[ 
     {firstName:{$gte:"bo"}}, 
     {firstName:{$lt:"bp"}} 
    ] 
} 
*/ 


//now library functions that will automatically generate the correct query and add it to `searchCriteria`. Of course for complicated queries you may have to modifiy it a bit. 
function getEndStr(str) { 
    var endStrArr = str.toLocaleLowerCase('en-US').split(""); 
    for (var i = endStrArr.length - 1; i >= 0; --i) { 
     var lastChar = endStrArr[i]; 
     if(lastChar === "z"){ 
      return endStrArr.join("") + "zzzzzzzzzzzz"; 
     } 
     var nextChar = String.fromCharCode(lastChar.charCodeAt(0) + 1); 
     if (nextChar === ":") 
      nextChar = "a"; 
     if (nextChar !== false) { 
      endStrArr[i] = nextChar; 
      return endStrArr.join(""); 
     } 
     endStrArr.pop(); 
    } 
} 
function addStartsWithQuery(searchCriteria, propertyName, str) { 
    if (!(typeof str === 'string') || !str.length) 
     return; 
    var endStr = getEndStr(str); 
    if (endStr) { 
     if (!searchCriteria.$and) 
      searchCriteria.$and = []; 
     searchCriteria.$and.push({ 
      [propertyName]: { 
       $gte: str 
      } 
     }); 
     searchCriteria.$and.push({ 
      [propertyName]: { 
       $lt: endStr 
      } 
     }); 
    } else { 
     searchCriteria[propertyName] = { 
      $gte: str 
     } 
    } 
} 

まあ、それはMongoDBのが正式にそれをサポートしていないが判明します!私はJIRAの問題にリンクしています。ここで、これを明確にしています。これは、残念なことに、照合の有用性を著しく低下させます。すぐにこれを修正しよう!技術的に言えば、インデックスを使用していても、インデックスは"[\"\", {})",をインデックスの境界の1つとして使用しているため、インデックスのすべてのアイテムが常に返されるため、インデックススキャンは役に立たないことに気付きました。クエリの次の段階では、通常のような結果がフィルタリングされます。彼らはそれを修正するために取得するには、この問題の

https://jira.mongodb.org/browse/DOCS-9933

投票! https://jira.mongodb.org/browse/SERVER-29865

+0

ありがとうございます。私は、ネームドmongodbの大文字と小文字を区別しないインデックスを使用しないようにします。 – Panoptik

+0

@Panoptik問題の末尾には、適切な回避策があります。 – user3413723

関連する問題