26

mongodb + node.js + mongoose.js ORM バックエンドを使用しています。

II に _id フィールドのないネストされたオブジェクトの配列があるとします。

mongoose.Schema({
  nested: [{
    _id: false, prop: 'string'
  }]
})

そして、ネストされたすべての objectds に _id フィールドを追加したいので、mongoose スキーマは次のようになります。

mongoose.Schema({
  nested: [{
    prop: 'string'
  }]
})

次に、スクリプトを実行して実稼働 DB を変更する必要がありますよね? そのような変化を処理する最善の方法は何ですか? 変更を実装するには、どのツール (またはアプローチ) を使用するのが最適ですか?

4

3 に答える 3

19

スキーマレス データベースの大きな利点の 1 つは、データベース全体を新しいスキーマ レイアウトで更新する必要がないことです。DB 内の一部のドキュメントに特定の情報がない場合、コードは代わりに適切な処理を実行するか、そのレコードに対して何かを実行することを選択できます。

もう 1 つのオプションは、必要に応じてドキュメントを遅延更新することです。これは、ドキュメントが再度表示されたときにのみ行われます。この場合、レコード/ドキュメントごとにバージョン フラグを設定することを選択できます。これは、最初は表示されないこともあります (したがって、「バージョン 0」を意味します)。それもオプションですが。代わりに、データベース アクセス コードは必要なデータを探します。存在しない場合は、コードの更新後に追加された新しい情報であるため、可能な限り結果を埋めます。

あなたの例では、コードが読み取られた(または更新後に書き戻された)ときに_id:false標準MongoIdフィールドに変換し、_id:false現在設定されている場合は、絶対に必要な場合にのみ変更して書き込みます。

于 2013-01-21T10:20:13.953 に答える
15

実際、コレクションを調べて各ドキュメントに新しいフィールドを追加するスクリプトを作成する必要があります。ただし、正確な方法は、DB のサイズとストレージ システムのパフォーマンスによって異なります。ドキュメントにフィールドを追加すると、そのサイズが変更されるため、ほとんどの場合、再配置が発生します。この操作は IO に影響を与え、IO によって制限されます。コレクションが数千のドキュメントであり、最大で 10 万にも及ぶ場合は、コレクション全体がおそらくメモリに収まり、すべての IO が後で発生するため、1 つのループで繰り返し処理することができます。ただし、コレクションが使用可能なメモリをはるかに超える場合、アプローチはより複雑になります。通常、MongoDB を本番環境で使用するには、次の手順に従います。

  • timeout=False でカーソルを開く
  • ドキュメントのチャンクをメモリに読み込む
  • これらのドキュメントに対して更新クエリを実行します
  • IO サブシステムの過負荷と本番アプリケーションの損傷を避けるために、しばらくスリープします。
  • 完了するまで繰り返します
  • カーソルを閉じます:)

ドキュメント チャンクのサイズとスリープ期間は、実験的に決定する必要があります。通常、移行期間中は mongostats で QR/QW を回避する必要があります。低速ドライブ (Amazon の EBS など) での大規模なコレクションの場合、この IO セーフなアプローチには数時間から数日かかることがあります。

于 2013-01-21T09:48:38.653 に答える