アーカイブパターン
数年にわたる履歴データを保存する必要がある場合、特に古いデータに頻繁にアクセスする必要がない場合、最も古いデータを最新のデータと同じデータベースに保存すると、パフォーマンスに悪影響が影響可能性があります。代わりに、古いデータをアーカイブし、そのデータを別のストレージ場所に移動するようにスキーマを設計できます。
このタスクについて
アーカイブされたデータの保存方法には複数のオプションがあります。例では、次のことができます。
Amazon S3 などの外部ファイルストレージにデータを移動します。
データを別のより低いクラスターに移動します。
同じクラスター上の別のコレクションにデータを移動します。
ほとんどの場合、コストとパフォーマンスの点で外部ファイルストレージにデータを移動することが最良のオプションです。ユースユースケースで外部ファイルストレージが使用できない場合は、別のクラスターまたはコレクションにデータを移動することを検討してください。
データ アーカイブに関するヒント
データアーカイブ設計パターンを実装する前に、次のベストプラクティスを検討してください。
アーカイブ データには、他のコレクションへの参照ではなく、埋め込みデータモデルを使用する必要があります。アーカイブ データをクエリする場合、データの関連するすべてのコンポーネントが同じ時間に取得されている必要があります。データを埋め込むと、クエリによって関連データがまとめて返されるようになります。
ドキュメントの経過時間は単一のフィールドに含まれている必要があります。
期限切れになったり、アーカイブに移動されたりしないドキュメントがある場合は、ドキュメント期間を
keep forever
または同様の string に設定して、ドキュメントがアクティブなコレクション内に維持されなければならないことを示します。MongoDB Atlasは Online アーカイブを提供しており、アクセス頻度の低いデータは Atlas クラスターからクラウドオブジェクトストレージ上のMongoDBが管理する読み取り専用フェデレーティッドデータベースインスタンスに移動されます。
Scenario
この例では 、あるeコマースストアが 5 年以上前に発生した販売のデータをアーカイブしたいと考えています。最初のデータセットにはすべての販売が含まれ、古い販売のドキュメントは別のコレクションに移動されます。
手順
サンプル データの入力
db.sales.insertMany( [ { customer_name: "Hiroshi Tanaka", products: [ { product_id: "P1001", name: "Wireless Headphones", quantity: 1, price: 59.99 }, { product_id: "P1002", name: "Phone Charger", quantity: 2, price: 14.99 } ], total_amount: 89.97, date: ISODate("2025-01-30T10:15:00Z") }, { customer_name: "Aisha Khan", products: [ { product_id: "P1003", name: "Laptop", quantity: 1, price: 899.99 } ], total_amount: 899.99, date: ISODate("2018-11-20T15:45:00Z") // Over 5 years ago }, { customer_name: "Fatima Al-Farsi", products: [ { product_id: "P1006", name: "Gaming Mouse", quantity: 1, price: 49.99 }, { product_id: "P1007", name: "Mechanical Keyboard", quantity: 1, price: 129.99 } ], total_amount: 179.98, date: ISODate("2017-06-15T12:00:00Z") // Over 5 years ago }, { customer_name: "Nguyen Minh", products: [ { product_id: "P1008", name: "Bluetooth Speaker", quantity: 2, price: 39.99 } ], total_amount: 79.98, date: ISODate("2025-01-26T09:20:00Z") } ] )
古いドキュメントをアーカイブするためのスクリプトを作成
注意
次のスクリプトではMongoDB Shell構文を使用します。ドライバーの集計とクエリ構文を確認するには、ドライバーのドキュメントを参照してください。
// Set a variable to five years before the time that the script runs const fiveYearsAgo = new Date(); fiveYearsAgo.setFullYear(fiveYearsAgo.getFullYear() - 5); // Write old sales to the 'archived_sales' collection const writeOldSalesPipeline = [ { $match: { date: { $lt: fiveYearsAgo } } }, { $merge: { into: { db: "test", coll: "archived_sales", }, on: "_id" } } ] db.sales.aggregate(writeOldSalesPipeline) // Delete old sales from the active 'sales' collection try { db.sales.deleteMany( { date : { $lt: fiveYearsAgo } } ); } catch (e) { print (e); }
結果
スクリプトの実行後、sales
コレクションには 5 年以上前に発生した販売が含まれなくなります。
db.sales.find()
出力:
[ { _id: ObjectId('679ced18fa29d32ca7d1abab'), customer_name: 'Hiroshi Tanaka', products: [ { product_id: 'P1001', name: 'Wireless Headphones', quantity: 1, price: 59.99 }, { product_id: 'P1002', name: 'Phone Charger', quantity: 2, price: 14.99 } ], total_amount: 89.97, date: ISODate('2025-01-30T10:15:00.000Z') }, { _id: ObjectId('679ced18fa29d32ca7d1abae'), customer_name: 'Nguyen Minh', products: [ { product_id: 'P1008', name: 'Bluetooth Speaker', quantity: 2, price: 39.99 } ], total_amount: 79.98, date: ISODate('2025-01-26T09:20:00.000Z') } ]
古い販売が archived_sales
コレクションに存在するようになりました。
db.archived_sales.find()
出力:
[ { _id: ObjectId('679ced18fa29d32ca7d1abac'), customer_name: 'Aisha Khan', products: [ { product_id: 'P1003', name: 'Laptop', quantity: 1, price: 899.99 } ], total_amount: 899.99, date: ISODate('2018-11-20T15:45:00.000Z') }, { _id: ObjectId('679ced18fa29d32ca7d1abad'), customer_name: 'Fatima Al-Farsi', products: [ { product_id: 'P1006', name: 'Gaming Mouse', quantity: 1, price: 49.99 }, { product_id: 'P1007', name: 'Mechanical Keyboard', quantity: 1, price: 129.99 } ], total_amount: 179.98, date: ISODate('2017-06-15T12:00:00.000Z') } ]