簡體   English   中英

貓鼬findOneAndUpdate:創建然后更新嵌套數組

[英]Mongoose findOneAndUpdate: create and then update nested array

我有一個程序,用於從服務器請求天氣數據,處理數據,然后使用貓鼬將其保存到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 }
     )

date對象看起來像這樣:

    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”,但是這樣做沒有任何反應。

問題是,第一次運行工作站數據時,我想在第三個代碼塊中創建一個格式為data對象的新文檔,然后在后續運行中,一旦該文檔已存在,請更新maxT數組具有新的價值。 有任何想法嗎?

您將得到以下輸出:

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

因為您正在整理文檔。 處理文檔數組時,上裝會變得有些復雜。

更新數組時,MongoDB知道data.0指向數組中的第一個元素。 但是,在插入時,MongoDB不能確定它是數組還是對象。 因此,它假定它是一個對象。 因此,它不會插入["val"] ,而是插入{"0": "val"}


最簡單的解決方案

不要使用upsert。 為每個新氣象站插入一個文檔,然后使用findOndAndUpdate將值推入文檔中的數組。 只要您第一次正確插入數組,就可以將它們壓入它們而不會變成對象。


如果data僅包含一個對象,則為另一種簡單解決方案

從您的問題來看,您似乎在data只有一個對象。 如果是這種情況,您可以將maxT數組maxT頂級,而不是成為數組中單個文檔的屬性。 然后它就像dates一樣。


更復雜的MongoDB 3.6解決方案

如果您真的不能沒有upserts,MongoDB 3.6就會引入過濾后的位置運算符$[<identifier>] 您可以使用此運算符來更新與查詢匹配的數組中的特定元素。 與簡單的位置運算符$ ,只要使用精確匹配,新的$[<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時該方法才可行。

暫無
暫無

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

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