2

このドキュメントに従って、事前に集計されたパフォーマンス メトリックをシャード mongodb に保存しようとしています。

私はそのように upsert を使用して存在する場合と存在しない場合があるレコード内の分のサブドキュメントを更新しようとしています (self.collectionは pymongo コレクションインスタンスです):

self.collection.update(query, data, upsert=True)

クエリ:

{   '_id': u'12345CHA-2RU020130304',
    'metadata': {   'adaptor_id': 'CHA-2RU',
                    'array_serial': 12345,
                    'date': datetime.datetime(2013, 3, 4, 0, 0, tzinfo=<UTC>),
                    'processor_id': 0}
}

データ:

{   'minute': {   '16': {   '45': 1.6693091}}}

問題は、この場合、「分」サブドキュメントには常に最後のhour: { minute: metric}エントリしかなく、分サブドキュメントは他の時間の新しいエントリを作成せず、常に 1 つのエントリを上書きすることです。

$set スタイルのデータ エントリでもこれを試しました。

{ '$set': {   'minute': {   '16': {   '45': 1.6693091}}}}

でも結局同じ。

私は何を間違っていますか?

4

2 に答える 2

2

リストされている両方の例で、フィールド ( 'minute') を特定の値に設定しているだけです。最初の更新時に追加する唯一の理由は、フィールド自体が存在しないため、作成する必要があるためです。

'minute'ここで何を撮影しているのかを正確に判断するのは難しいですが、スキーマを少し変更して配列にすることができると思います。次に、値が既に存在するかどうかに関係なく、または重複したくない場合$pushに値を追加するために使用できます。$addToSet

シェルで有効にするためにドキュメントを少し変更する必要があったため、私の_id(および他のいくつかのフィールド)はあなたのものとは少し異なりますが、説明するのに十分近いはずです:

db.foo.find({'_id': 'u12345CHA-2RU020130304'}).pretty()
{
        "_id" : "u12345CHA-2RU020130304",
        "metadata" : {
                "adaptor_id" : "CHA-2RU",
                "array_serial" : 12345,
                "date" : ISODate("2013-03-18T23:28:50.660Z"),
                "processor_id" : 0
        }
}

minute次に、単一のドキュメントではなく、ドキュメントの配列を持つフィールドを追加しましょう:

db.foo.update({'_id': 'u12345CHA-2RU020130304'}, { $addToSet : {'minute': { '16': {'45': 1.6693091}}}})
db.foo.find({'_id': 'u12345CHA-2RU020130304'}).pretty()
{
        "_id" : "u12345CHA-2RU020130304",
        "metadata" : {
                "adaptor_id" : "CHA-2RU",
                "array_serial" : 12345,
                "date" : ISODate("2013-03-18T23:28:50.660Z"),
                "processor_id" : 0
        },
        "minute" : [
                {
                        "16" : {
                                "45" : 1.6693091
                        }
                }
        ]
}

次に、追加を説明するために、少し異なるエントリを追加します (これを使用し$addToSetているため、新しいフィールドを追加するために必要です。

db.foo.update({'_id': 'u12345CHA-2RU020130304'}, { $addToSet : {'minute': { '17': {'48': 1.6693391}}}})
db.foo.find({'_id': 'u12345CHA-2RU020130304'}).pretty()
{
        "_id" : "u12345CHA-2RU020130304",
        "metadata" : {
                "adaptor_id" : "CHA-2RU",
                "array_serial" : 12345,
                "date" : ISODate("2013-03-18T23:28:50.660Z"),
                "processor_id" : 0
        },
        "minute" : [
                {
                        "16" : {
                                "45" : 1.6693091
                        }
                },
                {
                        "17" : {
                                "48" : 1.6693391
                        }
                }
        ]
}
于 2013-03-18T23:33:31.890 に答える
2

私はこのようにフィールドを設定することになりました:

クエリ:

{   '_id': u'12345CHA-2RU020130304',
    'metadata': {   'adaptor_id': 'CHA-2RU',
                    'array_serial': 12345,
                    'date': datetime.datetime(2013, 3, 4, 0, 0, tzinfo=<UTC>),
                    'processor_id': 0}
}

私は次のようにメトリックを設定しています:

data = {"$set": {}}

for metric in csv:
  date_utc = metric['date'].astimezone(pytz.utc)
  data["$set"]["minute.%d.%d" % (date_utc.hour,
                                date_utc.minute)] = float(metric['metric'])

次のようなデータを作成します。

{"$set": {'minute.16.45': 1.6693091,
          'minute.16.46': 1.566343,
          'minute.16.47': 1.22322}}

そのため、self.collection.update(query, data, upsert=True)実行時にこれらのフィールドが更新されます。

于 2013-03-19T21:07:45.113 に答える