簡體   English   中英

更新 MongoDB 中的嵌套數組對象

[英]Update nested array objects in MongoDB

我必須在 NodeJS 應用程序中處理以下類型的對象(使用 mongodb 驅動程序):

data_test = {
    "id": "105-20090412",
    "date": new Date('2020-09-04T14:00:00.000Z'),
    "station": {
        "name": "AQ105",
        "loc": {
            "type": "Point",
            "coordinates": [14.324498, 40.821930]
        },
        "properties": {}
    },
    "samples": [{
        "t": new Date('2020-09-04T14:14:00.000Z'),
        "data": {
            //"temp_celsius": 31.81,
            //"humRelPercent": 39,
            "press_mBar": 1021.12,
            "PM10": 200
        }
    }]
}

如上所述,我每 2 分鍾收到一次數據。 我想要:

  1. 如果收到的數據的 id 尚未出現在 MongoDB 上,請執行插入操作
  2. 如果接收到的數據有一個帶有日期(t 屬性)的示例對象,則向該對象添加屬性(例如不同傳感器的讀數)
  3. 如果接收到的數據有一個帶有日期(t 屬性)的樣本對象尚未出現在樣本數組中,則添加這個新對象

我想使用與 MongoDB 服務器往返的次要次數來執行上述操作。 我希望已經足夠清楚了。 有什么建議嗎? 提前致謝。

這是我的建議,這不是正確的答案。 您將需要擺弄查詢部分。 下面的查詢應該適用於 1 和 3,對於 2,您將不得不四處游盪。

db.collection.updateOne(
      { "id" : "105-20090412", "samples.t": <Date> },
      { $push: { "samples" : <sample> } },
      { $setOnInsert: { station: <station> } },
      { upsert: true }
   );

參考:

https://docs.mongodb.com/manual/reference/method/db.collection.updateOne/ https://docs.mongodb.com/manual/reference/operator/update/setOnInsert/#up._S_setOnInserthttps:// docs.mongodb.com/manual/reference/operator/update/push/

我終於找到了以下解決方案,也許不是最有效的解決方案:

  try {
        const db = client.db(dbName);
        const collection = db.collection(collectionName);

        // retrive id, station, date  and samplesToAdd as separate objects 
        let {
            id,
            ...dataToInsert
        } = data

        //id = new ObjectID(id)
        const queryBy_id = {
            _id: id
        }


        // first check if doc exists
        let res_query = await collection.findOne(queryBy_id)

        // if doc does not exists then insert a new one
        if (!res_query) {
            res_insert = await collection.insertOne({
                _id: id,
                ...dataToInsert
            })
            return res_insert;
        } else {
            // retrive samples from initial query
            let current_samples = res_query.samples

            // check if sample in dataToInsert yet exists 
            // use getTime to correctly compare dates
            let idx = current_samples.findIndex(x => x.t.getTime() == dataToInsert.samples[0].t.getTime())


            if (idx >= 0) {
                // find index of sample to update
                let current_t = current_samples[idx].t

                // merge data yet stored with new one
                current_samples.data = {
                    ...current_samples[idx].data,
                    ...dataToInsert.samples[0].data
                }

                let resUpdateSample = await collection.updateOne({
                    _id: id,
                    'samples.t': current_t
                }, {
                    $set: {
                        'samples.$.data': current_samples.data
                    }
                })
                return resUpdateSample

            } else {
                // add data to samples array
                let resAddToSamples = await collection.updateOne({
                    _id: id
                }, {
                    $push: {
                        samples: dataToInsert.samples[0]
                    }
                })
                return resAddToSamples
            }

        }

    } catch (err) {
        logger.error(err);
    }

我該如何改進? 謝謝。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM