[英]Update nested array objects in MongoDB
I have to deal with objects of the following type in a NodeJS app (using mongodb driver):我必须在 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
}
}]
}
I receive every 2 minutes data as above.如上所述,我每 2 分钟收到一次数据。 I want to:我想要:
I would like to do what described above with the minor count possible of round-trips to the MongoDB server.我想使用与 MongoDB 服务器往返的次要次数来执行上述操作。 I hope to have been clear enough.我希望已经足够清楚了。 Any suggestion?有什么建议吗? Thanks in advance.提前致谢。
Here's my suggestion, this is not the correct answer.这是我的建议,这不是正确的答案。 You will need to fiddle with the query portion.您将需要摆弄查询部分。 The query below should work for 1 & 3, for 2 you will have to play around.下面的查询应该适用于 1 和 3,对于 2,您将不得不四处游荡。
db.collection.updateOne(
{ "id" : "105-20090412", "samples.t": <Date> },
{ $push: { "samples" : <sample> } },
{ $setOnInsert: { station: <station> } },
{ upsert: true }
);
References:参考:
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/ 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/
I finally came to the following solution, perhaps not the most efficient one:我终于找到了以下解决方案,也许不是最有效的解决方案:
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);
}
How can I improve it?我该如何改进? Thanks.谢谢。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.