機能的な違い : Amazon DocumentDB と MongoDB - Amazon DocumentDB

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

機能的な違い : Amazon DocumentDB と MongoDB

Amazon DocumentDB (MongoDB 互換性) と MongoDB の機能上の違いを以下に示します。

Amazon DocumentDB の機能上の利点

暗示的なトランザクション

Amazon DocumentDB では、すべての CRUD ステートメント (findAndModifyupdateinsertdelete) は、複数のドキュメントを変更するオペレーションにおいてもアトミック性および整合性を保証します。Amazon DocumentDB 4.0 の起動により、マルチステートメントおよびマルチコレクションオペレーションの ACID プロパティを提供する明示的なトランザクションがサポートされるようになりました。Amazon DocumentDB でのトランザクションの使用の詳細については、「トランザクション」を参照してください。

アトミック性および整合性の両方の動作を満たす複数のドキュメントを変更する Amazon DocumentDB のオペレーションの例を次に示します。

db.miles.update( { "credit_card": { $eq: true } }, { $mul: { "flight_miles.$[]": NumberInt(2) } }, { multi: true } )
db.miles.updateMany( { "credit_card": { $eq: true } }, { $mul: { "flight_miles.$[]": NumberInt(2) } } )
db.runCommand({ update: "miles", updates: [ { q: { "credit_card": { $eq: true } }, u: { $mul: { "flight_miles.$[]": NumberInt(2) } }, multi: true } ] })
db.products.deleteMany({ "cost": { $gt: 30.00 } })
db.runCommand({ delete: "products", deletes: [{ q: { "cost": { $gt: 30.00 } }, limit: 0 }] })

updateManydeleteMany などの一括オペレーションを構成する個々のオペレーションはアトミックですが、一括オペレーション全体はアトミックではありません。たとえば、個々の挿入オペレーションがエラーなしで正常に実行された場合、insertMany オペレーション全体はアトミックです。insertMany オペレーションでエラーが発生した場合、insertMany オペレーション内の各挿入ステートメントはアトミックオペレーションとして実行されます。insertManyupdateMany、および deleteMany オペレーションに ACID プロパティが必要な場合の場合は、トランザクションを使用することをお勧めします。

機能的な違いの更新

Amazon DocumentDB は、お客様より依頼のあった機能からさかのぼって、MongoDB との互換性を改善し続けています。このセクションでは、移行とアプリケーション構築を容易にするため、Amazon DocumentDB から削除された機能的な違いについて説明します。

配列インデックス作成

2020 年 4 月 23 日以降、Amazon DocumentDB で 2,048 バイトを超える配列のインデックスを作成する機能がサポートされるようになりました。配列内の個々のキーの制限は依然として 2,048 バイトのままであり、これは MongoDB と一貫しています。

新しいインデックスを作成する場合、強化された機能を利用するためのアクションは必要ありません。既存のインデックスがある場合、インデックスを削除してから再作成することで、強化された機能を利用できます。強化された機能を使用した現在のインデックスバージョンは "v" : 3 です。

注記

本番クラスターの場合、インデックスの削除はアプリケーションのパフォーマンスに影響を与える可能性があります。本番システムに変更を加える場合、最初にテストし、注意して進めることをお勧めします。さらに、インデックスの再作成にかかる時間は、コレクションの全体的なデータサイズの関数になります。

次のコマンドを使用して、インデックスのバージョンをクエリできます。

db.collection.getIndexes()

このオペレーションによる出力は、次のようになります。この出力では、インデックスのバージョンは "v" : 3 です。これは最新のインデックスバージョンです。

[ { "v" : 3, "key" : { "_id" : 1 }, "name" : "_id_", "ns" : "test.test" } ]

マルチキーインデックス

2020 年 4 月 23 日より、Amazon DocumentDB では同じ配列内に複数のキーを持つ複合インデックスを作成する機能がサポートされるようになりました。

新しいインデックスを作成する場合、強化された機能を利用するためのアクションは必要ありません。既存のインデックスがある場合、インデックスを削除してから再作成することで、強化された機能を利用できます。強化された機能を使用した現在のインデックスバージョンは "v" : 3 です。

注記

本番クラスターの場合、インデックスの削除はアプリケーションのパフォーマンスに影響を与える可能性があります。本番システムに変更を加える場合、最初にテストし、注意して進めることをお勧めします。さらに、インデックスの再作成にかかる時間は、コレクションの全体的なデータサイズの関数になります。

次のコマンドを使用して、インデックスのバージョンをクエリできます。

db.collection.getIndexes()

このオペレーションによる出力は、次のようになります。この出力では、インデックスのバージョンは "v" : 3 です。これは最新のインデックスバージョンです。

[ { "v" : 3, "key" : { "_id" : 1 }, "name" : "_id_", "ns" : "test.test" } ]

文字列内の null 文字

2020 年 6 月 22 日現在、Amazon DocumentDB が文字列で null 文字 ('\0') をサポートするようになりました。

ロールベースのアクセスコントロール

2020 年 3 月 26 日現在、Amazon DocumentDB は組み込みロールによるロールベースのアクセスコントロール (RBAC) をサポートしています。詳細については、「ロールベースのアクセスコントロール」を参照してください。

$regex インデックス作成

2020 年 6 月 22 日現在、Amazon DocumentDB は $regex 演算子がインデックスを活用する機能をサポートするようになりました。

$regex 演算子を使用してインデックスを活用するには、hint() コマンドを使用する必要があります。hint() を使用する際は、$regex を適用するフィールドの名前を指定する必要があります。たとえば、product というフィールドにインデックス名 p_1 というインデックスがある場合、db.foo.find({product: /^x.*/}).hint({product:1}) では p_1 インデックスを使用しますが、db.foo.find({product: /^x.*/}).hint(“p_1”) ではインデックスを使用しません。インデックスが選択されているかどうかを確認するには、explain() コマンドを使用するか、低速クエリのログ記録にプロファイラーを使用します。例えば db.foo.find({product: /^x.*/}).hint(“p_1”).explain() です。

注記

hint() メソッドは、一度に 1 つのインデックスでのみ使用できます。

$regex クエリでのインデックスの使用は、プレフィックスを利用し、Im、または o 正規表現オプションを指定しない正規表現クエリに最適化されます。

$regex でインデックスを使用する場合は、重複値の数がコレクション内のドキュメントの総数の 1% 未満であるごく一部のフィールドにインデックスを作成することをお勧めします。例えば、コレクションに 100,000 個のドキュメントが含まれている場合、同じ値が発生する回数が 1000 回以下のフィールドにのみインデックスを作成します。

ネストされたドキュメントの投影

Amazon DocumentDB と MongoDB 3.6 における $project 演算子と機能の差は、Amazon DocumentDB 4.0 で解決されていますが、Amazon DocumentDB 3.6 では未サポートのままです。

Amazon DocumentDB 3.6 は、投影を適用するときにネストされたドキュメントの最初のフィールドのみを考慮しますが、MongoDB 3.6 はサブドキュメントを解析し、各サブドキュメントにも投影を適用します。

例えば、投影が “a.b.c”: 1 とすると、この動作は Amazon DocumentDB と MongoDB の両方で期待どおりに機能します。ただし、投影が {a:{b:{c:1}}} だとすると、Amazon DocumentDB 3.6 は投影を a にのみ適用し、bc には適用しません。Amazon DocumentDB 4.0では、投影 {a:{b:{c:1}}}ab、およびc に適用されます。

MongoDB との機能的な違い

Amazon DocumentDB は、独立した演算子$vectorSearchとして をサポートしていません。代わりに、 $search演算子vectorSearch内で がサポートされています。詳細については、「Amazon DocumentDB のベクトル検索」を参照してください。

OpCountersCommand

Amazon DocumentDB OpCountersCommand の動作は MongoDB の動作と次のように異なります。opcounters.command

  • MongoDB は挿入、更新、opcounters.command削除を除くすべてのコマンドをカウントしますが、Amazon DocumentDB はOpCountersCommandコマンドも除外します。find

  • Amazon DocumentDB は、内部コマンド (getCloudWatchMetricsV2など) をにカウントします。OpCountersCommand

管理データベースとコレクション

Amazon DocumentDB は管理者データベースまたはローカルデータベースをサポートしていません。また、MongoDB system.* または startup_log コレクションもサポートしていません。

cursormaxTimeMS

Amazon DocumentDB では、cursor.maxTimeMS はカウンターを getMore リクエストごとにリセットします。したがって、3000 ミリ秒 maxTimeMS が指定されている場合、クエリは 2800 ミリ秒 になり、getMore リクエストは 300 ミリ秒 かかり、カーソルはタイムアウトしません。カーソルがタイムアウトするのは、単一のオペレーション(クエリまたは個々の getMore リクエスト)の場合のみです。指定された maxTimeMS よりも多くかかります。さらに、カーソルの実行時間をチェックするスイーパーは、5 分単位で実行されます。

explain()

Amazon DocumentDB は、分散型で、耐障害性が高く、自己復旧ストレージシステムを利用する専用データベースエンジンで MongoDB 4.0 API をエミュレートします。その結果、クエリプランと explain() の出力は、Amazon DocumentDB と MongoDB の間で異なる場合があります。クエリプランを制御する場合は、$hint 演算子を使用して優先インデックスの選択を強制できます。

フィールド名の制限

Amazon DocumentDB はドット「.」をサポートしていません。ドキュメントフィールド名では、(例 : db.foo.insert({‘x.1’:1}))。

Amazon DocumentDB では、フィールド名の $ プレフィックスもサポートしていません。

例えば、Amazon DocumentDB または MongoDB で次のコマンドを試してください。

rs0:PRIMARY< db.foo.insert({"a":{"$a":1}})

MongoDB は以下を返します。

WriteResult({ "nInserted" : 1 })

Amazon DocumentDB はエラーを返します。

WriteResult({ "nInserted" : 0, "writeError" : { "code" : 2, "errmsg" : "Document can't have $ prefix field names: $a" } })
注記

この機能の違いには例外があります。$ プレフィックスで始まる次のフィールド名はホワイトリストに登録されており、Amazon DocumentDB で正常に使用できます : $id、$ref、$db。

インデックスビルド

Amazon DocumentDB では、任意の時点でコレクションにおいてインデックスの作成が 1 つのみ許可されます。フォアグラウンドまたはバックグラウンドのいずれかで実行されます。インデックス構築が現在進行中のときに、createIndex() または dropIndex() などの操作が同じコレクションで発生した場合、新しく試行された操作は失敗します。

デフォルトでは、Amazon DocumentDB と MongoDB バージョン 4.0 のインデックスビルドはバックグラウンドで行われます。MongoDB バージョン 4.2 以降では、createIndexes またはそのシェルヘルパー、createIndex()およびcreateIndexes()に指定されている場合、バックグラウンドインデックス構築オプションは無視されます。

有効期限 (TTL) インデックスは、インデックスの構築が完了した後、ドキュメントの期限切れが開始されます。

パスに空のキーでルックアップ

パスの一部として (例 : x.x..b) 空の文字列を含むキーを調べると、オブジェクトには空の文字列キーパス (例 : {"x" : [ { "" : 10 }, { "b" : 20 } ]}) が配列内にあり、Amazon DocumentDB は MongoDB で同じルックアップを実行する場合とは異なる結果を返します。

MongoDB では、空の文字列キーがパスルックアップの末尾にない場合に、配列内の空のキーパスルックアップが期待どおりに機能します。ただし、空の文字列キーがパスルックアップの末尾にある場合、配列は検索されません。

ただし、Amazon DocumentDB では、配列内の最初の要素のみが読み取られます。getArrayIndexFromKeyString は空の文字列を0 に変換するため、文字列キールックアップは配列インデックスルックアップとして扱われるためです。

MongoDB API、オペレーション、およびデータ型

Amazon DocumentDB は MongoDB 3.6 および 4.0 API と互換性があります。サポートされている機能のリスト up-to-date については、「」を参照してくださいサポートされている MongoDB API、オペレーション、およびデータ型

mongodump および mongorestore ユーティリティ

Amazon DocumentDB は管理者データベースをサポートしないため、mongodump または mongorestore ユーティリティを使用するときに、管理者データベースをダンプまたは復元しません。mongorestore を使用して、Amazon DocumentDB の新しいデータベースを作成するときに、復元オペレーションに加えてユーザーロールを再作成する必要があります。

注記

Amazon DocumentDB には、バージョン 100.6.1 までの MongoDB データベースツールをお勧めします。MongoDB データベースツールのダウンロードには、こちらからアクセスできます。

結果の順序

Amazon DocumentDB では、結果セットの暗黙的な並べ替え順序は保証されません。結果セットの順序を確実にするには、sort() を使用してソート順を明示的に指定します。

次の例では、在庫フィールドに基づいて、インベントリ収集の項目を降順にソートします。

db.inventory.find().sort({ stock: -1 })

$sort 集約ステージを使用する場合は、$sort ステージが、集約パイプラインの最後のステージでない限り、並べ替え順序は保持されません。$sort 集約ステージと組み合わせた $group 集約ステージを使用する場合、$sort 集約ステージはおよび $first および $last アキュムレータにのみ適用されます。Amazon DocumentDB 4.0 では、$push のサポートが追加され、前の $sort ステージ並べ替え順序を尊重します。

再試行可能な書き込み

MongoDB 4.2 互換ドライバーから、再試行可能な書き込みがデフォルトで有効になっています。ただし、Amazon DocumentDB は現在、再試行可能な書き込みをサポートしていません。機能の違いは、次のようなエラーメッセージで示されます。

{"ok":0,"errmsg":"Unrecognized field: 'txnNumber'","code":9,"name":"MongoError"}

再試行可能な書き込みは、接続文字列 (例: MongoClient("mongodb://my.mongodb.cluster/db?retryWrites=false"))または MongoClient コンストラクターのキーワード引数 (例: MongoClient("mongodb://my.mongodb.cluster/db", retryWrites=False))

次に、接続文字列の再試行可能な書き込みを無効にする Python の例を示します。

client = pymongo.MongoClient('mongodb://<username>:<password>@docdb-2019-03-17-16-49-12.cluster-ccuszbx3pn5e.us-east-1.docdb.amazonaws.com:27017/?replicaSet=rs0',w='majority',j=True,retryWrites=False)

スパースなインデックス

クエリで作成したスパースなインデックスを使用するには、インデックスをカバーするフィールドで $exists 句を使用する必要があります。$exists を省略した場合、Amazon DocumentDB はスパースなインデックスを使用しません。

次に例を示します。

db.inventory.count({ "stock": { $exists: true }})

スパースなマルチキーインデックスの場合、ドキュメントのルックアップによって値のセットが生成され、インデックス付きフィールドのサブセットのみが見つからない場合、Amazon DocumentDB は一意キー制約をサポートしません。たとえば、"a" : [ { "b" : 2 }, { "c" : 1 } ] を入力すると、"a.c" がインデックスに格納されているため、createIndex({"a.b" : 1 }, { unique : true, sparse :true }) はサポートされません。

$all 式内での $elemMatch の使用

Amazon DocumentDB は $elemMatch 演算子が $all 内にある表現の使用をサポートしていません。回避策として、次のように $and 演算子を $elemMatch で使用できます。

元のオペレーション:

db.col.find({ qty: { $all: [ { "$elemMatch": { part: "xyz", qty: { $lt: 11 } } }, { "$elemMatch": { num: 40, size: "XL" } } ] } })

更新されたオペレーション:

db.col.find({ $and: [ { qty: { "$elemMatch": { part: "xyz", qty: { $lt: 11 } } } }, { qty: { "$elemMatch": { qty: 40, size: "XL" } } } ] })

$ne$nin$nor$not$exists および $elemMatch のインデックス作成

Amazon DocumentDB は、現在、$ne$nin$nor$not$exists、と $distinct の演算子でのインデックス使用をサポートしていません。そのため、これらの演算子を利用した結果は、収集スキャンになります。これらの演算子のいずれかを使用する前にフィルターまたは照合を実行すると、スキャン対象のデータ量が減り、パフォーマンスが向上します。

Amazon DocumentDB では、Amazon DocumentDB 5.0 とエラスティッククラスターの$elemMatchオペレーターによるインデックススキャンのサポートが追加されました。インデックススキャンは、クエリのみのフィルタに 1 つのレベルの$elemMatchフィルタがある場合はサポートされますが、ネストされた$elemMatchクエリが含まれる場合はサポートされません。

Amazon DocumentDB 5.0 でのインデックススキャンをサポートする$elemMatchクエリシェイプ:

db.foo.find( { "a": {$elemMatch: { "b": "xyz", "c": "abc"} } })

Amazon DocumentDB 5.0 でインデックススキャンをサポートしない $elemMatch クエリシェイプ:

db.foo.find( { "a": {$elemMatch: { "b": {$elemMatch: { "d": "xyz", "e": "abc"} }} } })

$lookup

Amazon DocumentDB は、等価一致 (左外部結合など) を行う機能をサポートし、相関関係のないサブクエリもサポートしますが、相関関係のあるサブクエリはサポートしません。

$lookup でインデックスを利用する

$lookup ステージ演算子で、インデックスを利用できるようになりました 。ユースケースに基づいて、パフォーマンスを最適化するために使用できるインデックス作成アルゴリズムが複数あります。このセクションでは、$lookup のさまざまなインデックス作成アルゴリズムについて説明し、ワークロードに最適なオプションを選択するのに役立ちます。

デフォルトでは、Amazon DocumentDB は allowDiskUse:false が使用された場合はハッシュアルゴリズムを使用し、allowDiskUse:true が使用された場合はソートマージを使用します。ユースケースによっては、クエリオプティマイザで別のアルゴリズムを使用するように強制することが望ましい場合があります。以下は、集約演算子が利用できる、さまざまな $lookup インデックス作成アルゴリズムです。

  • ネストループ:外部コレクションが 1 GB 未満で、外部コレクションのフィールドにインデックスがある場合は、通常、ネストループプランがワークロードに役立ちます。ネスト・ループ・アルゴリズムを使用している場合、説明プランではステージがNESTED_LOOP_LOOKUPと表示されます。

  • ソートマージ:ソートマージプランは、外部コレクションのルックアップに使用されるフィールドにインデックスがなく、作業データセットがメモリに収まらない場合にワークロードにとって有益です。ソートマージアルゴリズムが使用されている場合、説明プランではステージを SORT_LOOKUP と表示されます。

  • ハッシュ:外部コレクションが 1 GB 未満で、作業データセットがメモリに収まる場合は、通常、ハッシュプランがワークロードにとって有益です。ハッシュアルゴリズムが使用されている場合、説明プランはステージを HASH_LOOKUP と表示されます。

クエリに対して explain を使用することで、$lookup 演算子に使用されているインデックス作成アルゴリズムを特定できます。以下に例を示します。

db.localCollection.explain(). aggregate( [ { $lookup: { from: "foreignCollection", localField: "a", foreignField: "b", as: "joined" } } ] output { "queryPlanner" : { "plannerVersion" : 1, "namespace" : "test.localCollection", "winningPlan" : { "stage" : "SUBSCAN", "inputStage" : { "stage" : "SORT_AGGREGATE", "inputStage" : { "stage" : "SORT", "inputStage" : { "stage" : "NESTED_LOOP_LOOKUP", "inputStages" : [ { "stage" : "COLLSCAN" }, { "stage" : "FETCH", "inputStage" : { "stage" : "COLLSCAN" } } ] } } } } }, "serverInfo" : { "host" : "devbox-test", "port" : 27317, "version" : "3.6.0" }, "ok" : 1 }

explain() メソッドを使用する代わりに、プロファイラを使用して、$lookup 演算子の使用で利用されているアルゴリズムを表示することができます。プロファイラーの詳細については、「Amazon DocumentDB オペレーションのプロファイリング」を参照してください。

planHint を使用​する

クエリオプティマイザで別のインデックス作成アルゴリズムと $lookup を強制的に使用する場合、planHint を使用できます。これを行うには、集約ステージオプションのコメントを使用して、別のプランを強制します。コメントの構文の例を以下に示します。

comment : { comment : “<string>”, lookupStage : { planHint : “SORT” | “HASH” | "NESTED_LOOP" } }

以下は、planHint を使用してクエリオプティマイザに HASH インデックスアルゴリズムの使用を強制する例です。

db.foo.aggregate( [ { $lookup: { from: "foo", localField: "_id", foreignField: "_id", as: "joined" }, } ], { comment : "{ \\"lookupStage\\" : { \\"planHint\\": \\"HASH\\" }}"

どのアルゴリズムがワークロードに最適かをテストするには、executionStats パラメータにある explain メソッドを使用して、$lookup ステージの実行時間を測定することができ、これはインデックス作成アルゴリズム (つまり、HASH / SORT/NESTED_LOOP) を変更しながらできます。

次の例は executionStats を使用して、$lookup ステージの実行時間を測定するには、SORT アルゴリズムを使用します。

db.foo.explain(“executionStats”).aggregate( [ { $lookup: { from: "foo", localField: "_id", foreignField: "_id", as: "joined" }, } ], { comment : "{ \\"lookupStage\\" : { \\"planHint\": \\"SORT\\" }}"