0

時系列をMongoDBに保存していますが、構造は次のとおりです。

{
  "_id" : ObjectId("5128e567df6232180e00fa7d"),
  "values" : [563.424, 520.231, 529.658, 540.459, 544.271, 512.641, 579.591, 613.878, 627.708, 636.239, 672.883, 658.895, 646.44, 619.644, 623.543, 600.527, 619.431, 596.184, 604.073, 596.556, 590.898, 559.334, 568.09, 568.563],
  "day" : 20110628,
}

values-array は、各時間の値を表しています。そのため、 position0 = first hourなど1 = second hourと同様に重要です。

特定の時間の値を更新するのは非常に簡単です。たとえば、1 日の 7 時間を更新するには、次のようにします。

db.timeseries.update({day:20130203},{$set : {values.6 : 482.65}}, {upsert : true})

私の問題は、このようにupsertを使用したいということです

db.timeseries.update({day:20130203},{$set : {values.6 : 482.65}})

しかし、ドキュメントが存在しない場合、MongoDB は埋め込み配列ではなく埋め込みドキュメントを作成します。このような:

{
  "_id" : ObjectId("5128e567df6232180e00fa7d"),
  "values" : {"6" : 482.65},
  "day" : 20130203,
}

この問題を解決する機能を追加するためのチケットがここにありますが、その間、私の場合はこれを解決するための回避策を考え出しました。

私がしていることは、最初に day-field に uniqe-index を作成したことです。そして、1 時間ごとのボリュームをアップサートするときはいつでも、次の 2 つのコマンドを実行します。

db.timeseries.insert({day:20130203, values : []}); // Will be rejected if it exists
db.timeseries.update({day:20130203},{$set : {values.6 : 482.65}});

最初のステートメントは新しいドキュメントを作成しようとしました - uniqe-index のおかげで、挿入が既に存在する場合は拒否されます。そうでない場合は、value-field の配列が埋め込まれたドキュメントが作成されます。これにより、更新が確実に機能します。

結果:

{
  "_id" : ObjectId("5128e567df6232180e00fa7d"),
  "values" : [null,null,null,null,null,null,482.65],
  "day" : 20130203,
}

そして、これが私の質問です

本番環境で、このような複数のコマンドが同時に実行される場合、挿入コマンドの後に更新コマンドが実行されることを確認できますか? 両方のコマンドをアンセーフ モードで実行したいことに注意してください。つまり、サーバーからの応答を待ちません。

(パフォーマンスの観点から、私の回避策についてここにコメントすることも興味深いでしょう。)

4

2 に答える 2

1

一般に、クライアントからの 2 つの要求が同じ接続を使用するようにする方法があります。同じ接続を使用することで、サーバー上で厳密な実行順序を強制します。

これを達成する方法は、ドライバーによって異なります。

Asynchronous Java Driverの場合、最初の MongoClient インスタンスから「シリアル化された」MongoClient を作成できます。これにより、すべてのリクエストが単一の接続を使用することが保証されます。

10gen Javaドライバーの場合、(ThreadLocal を介して) 自動的に同じ接続を使用しようとします。DB.requestStart()/DB.requestEnd() メソッドを介して、コマンドのグループをパイプライン処理する必要があるというヒントをドライバーに与えることもできます。

startRequest/endRequest は、ほとんどの 10gen ドライバーに適用されます。別の例として、PyMongo ドライバー mongo_client にはstart_request() /end_request() ペアがあります。

于 2013-02-24T15:49:47.283 に答える
0

パフォーマンスの観点からは、データベースへのアクセスを 2 回使用するよりも 1 回だけ使用する方が適切です。値フィールドの更新に $set の代わりに $push を使用できませんか?

于 2013-02-24T16:20:49.697 に答える