gpt4 book ai didi

javascript - Mongoose findOneAndUpdate : create and then update nested array

转载 作者:行者123 更新时间:2023-12-03 02:19:59 25 4
gpt4 key购买 nike

我有一个程序,我从服务器请求天气数据,处理数据,然后使用 mongoose 将其保存到 mlab 帐户。我正在收集 10 年的数据,但我请求数据的 API 一次只允许请求大约一年的数据。

我正在使用 findOndAndUpdate 创建/更新每个气象站的文档,但在更新数据对象中的数组时遇到问题。 (可能不是描述它的最佳方式......)

例如,这是模型:

    const stnDataSchema = new Schema(
{
station: { type: String, default: null },
elevation: { type: String, default: null },
timeZone: { type: String, default: null },
dates: {},
data: {}
},
{ collection: 'stndata' },
{ runSettersOnQuery: true }
)

日期对象如下所示:

    dates: ["2007-01-01",
"2007-01-02",
"2007-01-03",
"2007-01-04",
"2007-01-05",
"2007-01-06",
"2007-01-07",
"2007-01-08",
"2007-01-09"]

数据对象如下:

    "data": [
{
"maxT": [
0,
null,
4.4,
0,
-2.7,
etc.....

我想要发生的是,当我运行 findOneAndUpdate 时,我想根据站点查找文档,然后将新的 maxT 值和日期附加到相应的数组中。我让它适用于日期数组,但由于我更新的元素是嵌套的,因此数据数组遇到了麻烦。我试过这个:

    const update = {
$set: {'station': station, 'elevation': elevation, 'timeZone': timeZone},
$push: {'dates': datesTest, 'data.0.maxT': testMaxT}};
StnData.findOneAndUpdate( query, update, {upsert: true} ,
function(err, doc) {
if (err) {
console.log("error in updateStation", err)
throw new Error('error in updateStation')
}
else {
console.log('saved')

但在 mlab 中得到如下输出:

    "data": {
"0": {
"maxT": [
"a",
"b",

问题是我得到的是“0”而不是一个元素的数组。我尝试了“data[0].maxT”,但是当我这样做时什么也没有发生。

问题是,第一次运行站的数据时,我想创建一个新文档,其中包含第三个代码块中格式的数据对象,然后在后续运行中,一旦该文档已经存在,就更新具有新值的 maxT 数组。有什么想法吗?

最佳答案

您将得到以下输出:

 "data": {
"0": {
"maxT": [
"a",
"b",

因为您正在更新插入文档。处理文档数组时,更新插入会变得有点复杂。

更新数组时,MongoDB 知道 data.0 指的是数组中的第一个元素。然而,在插入时,MongoDB 无法判断它是数组还是对象。所以它假设它是一个对象。因此,它不是插入 ["val"] ,而是插入 {"0": "val"}

<小时/>

最简单的解决方案

不要使用更新插入。为每个新气象站插入一个文档,然后使用 findOndAndUpdate 将值推送到文档中的数组中。只要你第一次正确插入数组,你就能够推送它们,而不会让它们变成对象。

<小时/>

如果 data 仅包含一个对象,则另一种简单解决方案

从您的问题来看,您在 data 中似乎只有一个对象。如果是这种情况,您可以将 maxT 数组设为顶级,而不是作为数组中单个文档的属性。那么它的行为就像 dates

<小时/>

更复杂的 MongoDB 3.6 解决方案

如果您确实离不开更新插入,MongoDB 3.6 引入了过滤位置运算符 $[<identifier>] 。您可以使用此运算符来更新数组中与查询匹配的特定元素。 Unlike the simple positional operator $ ,只要使用精确匹配,新的 $[<identifier>] 运算符就可以用于更新插入。

您可以在此处阅读有关此运算符的更多信息:https://docs.mongodb.com/manual/reference/operator/update/positional-filtered/

因此,您的 data 对象需要有一个可以完全匹配的字段(例如 name )。示例查询如下所示:

let query = {
_id: 'idOfDocument',
data: [{name: 'subobjectName'}] // Need this for an exact match
}

let update = {$push: {'data.$[el].maxT': testMaxT}}

let options = {upsert: true, arrayFilters: [{'el.name': 'subobjectName'}]}

StnData.findOneAndUpdate(query, update, options, callbackFn)

正如您所看到的,这增加了更多的复杂性。忘记尝试进行更新插入会更容易。只需执行一次插入然后更新即可。

此外mLab目前不支持MongoDB 3.6。因此,在支持 3.6 之前,使用 mLab 时此方法不可行。

关于javascript - Mongoose findOneAndUpdate : create and then update nested array,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49203915/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com