3

配列全体でドキュメントを検索するだけでよいコレクションがあります。その配列の1つの値だけでドキュメントを検索したいというシナリオは考えられません。残念ながら、配列値に対して常にアクティブ化されているマルチキー機能は、明らかに非アクティブ化できません。

ドキュメントには、「インデックスは値のサブセット(現在は最初の値)を検索するために使用され、次にドキュメントが完全に一致するかどうかが検査されます」と記載されています。私の場合、これによりパフォーマンスが大幅に低下すると思います。インデックスにもかかわらず、一部のルックアップには70ミリ秒と数分かかります。これは、最初の要素によっては、MongoDBが数千または数十万のドキュメントを検索しなければならない場合があるためです。少なくともそれが私の理論です。

この問題を回避する方法はありますか、それとも配列をシリアル化して文字列として保存する必要がありますか?

前もって感謝します!

4

1 に答える 1

1

おそらく、次のようなサブドキュメントを使用できます。

{
  array_sub_doc: { arr: [1,2,3,4,5] }
}

あなたが次のような試合をすることができるように:

db.coll.ensureIndex({array_sub_doc:1});
db.coll.find({array_sub_doc: {arr:[1,2,3,4,5]}})

更新大規模なアレイで障害が発生した原因を発見しました。800バイトを超えるインデックスキーはインデックス付けされません。したがって、大きなサブドキュメントがあり、それにインデックスを付けた場合、それが800バイトを超えていて、それを検索しようとしても、それは見つかりません。インデックスを削除して同じサブドキュメントを再度検索すると、そのサブドキュメントが見つかります(ただし、完全なコレクションスキャンになります)。

これは制限としてここに文書化されており、将来のリリースで削除される予定です:https ://jira.mongodb.org/browse/SERVER-3372

したがって、これは一般的に小さなアレイで機能します。

誰かが試してみたい場合に備えて、いくつかのテストコードを次に示します。

var randomArray = function() {
  var len = 80;
  var randomarr = new Array();
  for (var i=0; i<len; i++) {
    randomarr.push(Math.floor(Math.random() *10000));
  }
  return randomarr;
}

var insert = function() {
  db.Test2.ensureIndex({array_sub_doc:1});
  for(var i=0;i<10000;i++) {
    db.Test2.save({array_sub_doc: {arr: randomArray()}});
  }
}

db.Test2.remove();
insert();

var one = db.Test2.findOne();
db.Test2.findOne({array_sub_doc:one.array_sub_doc});

//...

db.Test2.find({array_sub_doc:one.array_sub_doc}).explain(0);
/* outputs:
{
  "cursor" : "BtreeCursor array_sub_doc_1",
  "nscanned" : 1,
  "nscannedObjects" : 1,
  ...
*/
于 2012-01-18T17:59:25.653 に答える