3

Windows 7 64 SP1 -- MongoDB 2.2.0-rc2 -- Boost 1.42 -- MS VS 2010 Ultimate -- C++ ドライバー

「Mongo in Action」に従って、シェルで:

for(i=0; i<200000; i++){
  db.numbers.save({num: i});
}

db.numbers.find() の表示:

{ "_id": ObjectId("4bfbf132dba1aa7c30ac830a"),"num" : 0 }
{ "_id": ObjectId("4bfbf132dba1aa7c30ac830b"),"num" : 1 }
{ "_id": ObjectId("4bfbf132dba1aa7c30ac830c"),"num" : 2 }
{ "_id": ObjectId("4bfbf132dba1aa7c30ac830d"),"num" : 3 }
...

したがって、C++ で複製する場合:

// Insert 200,000 documents
for ( int i = 0; i < 200000 ; i++)
  c.insert(dc,BSON(GENOID << "num" << i));

//Display the first 20 documents
Query qu = BSONObj();
auto_ptr<DBClientCursor> cursor = c.query(dc,qu); 
for ( int i = 0 ; i < 20 ; i++){
  cout << cursor->next().toString() << endl;
}

出力:

{ "_id" : ObjectId("504bab737ed339cef0e26829"), "num" : 199924 }
{ "_id" : ObjectId("504bab737ed339cef0e2682a"), "num" : 199925 }
{ "_id" : ObjectId("504bab737ed339cef0e2682b"), "num" : 199926 }
{ "_id" : ObjectId("504bab737ed339cef0e2682c"), "num" : 199927 }
....

シェルで db.numbers.find() を呼び出すと、同じ出力が得られます。{"num" : 0} で始まっていないのはなぜですか? それが存在します:

> db.numbers.find({"num" : 0})
{ "_id" : ObjectId("504bab417ed339cef0df5b35"), "num" : 0 }

{"num" : 0} の _id は、{"num" : 199924} の _id の前にあります

そして、「_id」のインデックスが存在します:

> db.numbers.getIndexes()
[
    {
            "v" : 1,
            "key" : {
                    "_id" : 1
            },
            "ns" : "learning.numbers",
            "name" : "_id_"
    }
]

クエリ コードを変更して _id による並べ替えを追加すると、次のようになります。

auto_ptr<DBClientCursor> cursor = c.query(dc,qu.sort("_id")); 

次に、順番に印刷します。

{ "_id": ObjectId("4bfbf132dba1aa7c30ac830a"),"num" : 0 }
{ "_id": ObjectId("4bfbf132dba1aa7c30ac830b"),"num" : 1 }
...

これは、ドキュメントの小さなコレクション (たとえば 200) では発生しません。

質問: C++ クエリが _id でコレクションのインデックスを使用していないように見えるのはなぜですか? または、この明らかな異常を他に説明するものは何ですか (または私の理解の欠如?

4

2 に答える 2

2

索引付けとソートは別個の概念です。結果を並べ替えなくても、インデックス内のデータを見つけることができます。インデックスを使用せずに結果を並べ替えることもできます (ただし、これはお勧めしません)。

のソート順を指定していないため、結果は自然な順序find()で返されます。ドキュメントを挿入しただけで (削除も更新もしていない) コレクションの場合、自然順序は挿入順序に近似するはずです (ただし、挿入順序で維持されるキャップ付きコレクションを使用している場合を除きます)。

ドキュメントの削除または更新を開始すると (ドキュメントが移動される可能性があります)、MongoDB の事前割り当てデータ ファイルに空き領域の「ギャップ」が作成されます。MongoDB は、新しいドキュメントの挿入/移動のために空き領域を再利用します。そのため、時間の経過とともに、自然な順序は挿入順序と一致しなくなります。

特定の並べ替え順序で結果が期待される場合は、これをクエリに含める必要があります。

于 2012-09-08T23:04:37.207 に答える
0

@stenniありがとうございます - これらの「ギャップ」が問題であり、私を解決策に導きました。シェルでの自然な順序は、クエリの際に C++ ドライバーよりも「自然」に見え、後者は非常に大きな「num」で始まります。ただし、欠点は私の方法論にあります。

  1. シェルに 200000 ドキュメントを挿入します。
  2. db.numbers.find(); リストされた最初のドキュメントは{"num" : 0}
  3. db.numbers.remove()
  4. C++ ドライバーで 200000 ドキュメントを挿入
  5. db.numbers.find(); リストされた最初のドキュメントは{"num" : SomeVeryLargeNumber}

代わりにdb.numbers.drop()、実際にコレクションを削除する必要がありました。これは、ステップ 5 の最初のドキュメントが であることを意味します{"num" : 0}db.numbers.remove明らかにギャップを保っています。

于 2012-09-09T05:31:25.987 に答える