mongodb 更新嵌套數組的值

来源:https://www.cnblogs.com/zhongchengyi/archive/2020/01/09/12162792.html
-Advertisement-
Play Games

概要 本文主要講述在 mongodb 中,怎麼更新嵌套數組的值。 使用$更新數組 測試 for (let i = 0; i < 3; i++) { let data = { name1_1: 'test' + i, arr_1: [{ a: i, b: 2 }, { a: i + 1, b: 2 } ...


概要

本文主要講述在 mongodb 中,怎麼更新嵌套數組的值。

 使用$更新數組

  1. 基本語法  { "<array>.$" : value } 
  2. 可以用於:update, findAndUpdate 等方法
  3. $是一個占位符一樣的存在。代表被匹配的數組中的一個元素
  4. 可以匹配一個數組,匹配多個是會異常  index 0: 2 - Too many positional (i.e. '$') elements found in path ... ,即:只能在一層嵌套的數組中使用 $
  5. 示例 
    db.collection.update(
       { <array>: value ... },
       { <update operator>: { "<array>.$" : value } }
    )

     

 測試

  1.     創建一個測試數據
    for (let i = 0; i < 3; i++) {    
        let data = {
            name1_1: 'test' + i,
            arr_1: [{
                a: i,
                b: 2
            }, {
                a: i + 1,
                b: 2
            }]
        };
        db.nestedUpdate.insert(data);
    }
    創建數據腳本

    數據截圖:

     

  2. 我想更新arr_1數組中,a = 1 的對象,更新為 {a:11,b:12} 運行更新代碼,如下:
    db.nestedUpdate.updateMany({
        'arr_1.a': 1
    }, {
        $set: {
            'arr_1.$.a': 11,
            'arr_1.$.b': 12,
        }
    })

     運行後數據截圖:

  3.   針對上述結構,更新 a= 11 的對象值(與上面不同,上面是更新對象裡面的一個值),運行一下代碼:
    db.nestedUpdate.updateMany({
        'arr_1.a': 11
    }, {
        $set: {
       'arr_1.$': {a:11, c:[1,2,3]}
    } })

    運行結果:

     

  4.  繼續編輯,修改 arr_1.c 的元素,很容易想到如下:

    db.nestedUpdate.updateMany({
        'arr_1.c': 1
    }, {
        $set: {
            'arr_1.$.$': 11,
        }
    })

    然而,最終的運行結果卻是: [Error] index 0: 2 - Too many positional (i.e. '$') elements found in path 'arr_1.$.$' 

     那麼,我想更新數組中的數組下的一個元素這麼辦呢?下麵介紹兩種方法:1、遍曆數組修改,2、使用 arrayFilter。個人推薦 arrayFilter 方式。

.find.foreach + save (迴圈判斷保存法)

  1. 通過 .find 找到滿足條件的集合,(但只能找到根節點)
  2. 遍歷需要修改的節點,修改其值,(先遍歷arr_1, 在遍歷 arr_1.c)
  3. 把修改完成的對象,通過 save 方法更新回資料庫。
  4. 代碼如下
    // 查找所有
    var all1 = db.nestedUpdate.find({});
    all1.forEach(function(it) {   
        var modified = false;
            // 遍歷 arr_1
        for (var i = 0; i < it.arr_1.length; ++i) {
            var ac1 = it.arr_1[i];
            // 判斷需要修改的
                    if (ac1.c && ac1.c.length > 0 && ac1.c[0] == 1) {
                ac1.c[0] = 1111;
                modified = true;
            }
        }
        
        if (modified) {
            db.nestedUpdate.save(it);
        }
    })

 利用arrayFilter

  • 基本語法
db.collection.updateMany(
   { <query conditions> },
   { <update operator>: { "<array>.$[<identifier>]" : value } },
   { arrayFilters: [ { <identifier>: <condition> } ] }
)

 註意

  • arrayFilter 數組中的頂級欄位不能重覆,如下:出現了兩個 idx0,運行報錯 index 0: 9 - Found multiple array filters with the same top-level field name idx0 
    db.nestedUpdate.updateMany({}, {
        $set: {
            'arr_1.$[idx0].c.$[idx1]': 1
        }
    }, {
        arrayFilters: [
            {
                // idx0 滿足條件: 需存在 c 欄位
                'idx0.c': {
                    $exists: true
                },            
            },
            {
                'idx0.a': 1,            
            },
            {
                // idx1: 滿足 值為 111
                'idx1': 1111
            }
        ]
    });
    > [Error] index 0: 9 - Found multiple array filters with the same top-level field name idx0
      at line 1, column 1
    View Code
  • arrayFilter 中可以嵌套條件,如:
    db.nestedUpdate.updateMany({}, {
        $set: {
            'arr_1.$[idx0].c.$[idx1]': 1
        }
    }, {
        arrayFilters: [
            {
                // idx0 滿足條件: 需存在 c 欄位
                'idx0.c': {
                    $exists: true
                },
                'idx0.a': 1,
            },
            {
                // idx1: 滿足 值為 111
                'idx1': 1111
            }
        ]
    });
    
    // 或
    
    db.nestedUpdate.updateMany({}, {
        $set: {
            'arr_1.$[idx0].c.$[idx1]': 1
        }
    }, {
        arrayFilters: [
            {
                // idx0 滿足條件: 需存在 c 欄位
                idx0: {
                    c: {
                        $exists: true
                    },
                    a: 1
                }
            },
            {
                // idx1: 滿足 值為 111
                'idx1': 1111
            }
        ]
    });
    View Code
  • arrayFilter 必須包含所有的索引的條件。否則出現錯誤 [Error] index 0: 2 - No array filter found for identifier 'idx2' in path 'arr_1.$[].arr_1_1.$[idx1].arr1_1_1.$[idx2]' 
    db.nestedUpdate1.updateMany({}, {
        $set: {
            'arr_1.$[].arr_1_1.$[idx1].arr1_1_1.$[idx2]': null
        }
    }, {
        arrayFilters: [
            {
                // idx1: 滿足 name <= 1
                'idx1.name': {
                    $lte: 1
                }
            },
            
        ]
    })
    > [Error] index 0: 2 - No array filter found for identifier 'idx2' in path 'arr_1.$[].arr_1_1.$[idx1].arr1_1_1.$[idx2]'
      at line 1, column 1
    > 時間: 0.003s
    完整代碼
  • $[idx] 中的idx 可以自定義名字,只需要arrayFilter中名字一樣就可以,如 $[i], $[j]
  • 不止updateMany可以用,update、findAndUpdate、findAndModify 等也可以用
  • 可以與$[] 一起使用,需保證數組中的所有元素都滿足後面的條件,如:
    db.nestedUpdate1.updateMany({}, {
        $set: {
            'arr_1.$[].arr_1_1.$[idx1].arr1_1_1.$[idx2]': null
        }
    }, {
        arrayFilters: [
            {
                // idx1: 滿足 name <= 1
                'idx1.name': {
                    $lte: 1
                }
            },
            {
                idx2: 1
            }
        ]
    })

    運行示意:

     

     


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 網上查了很多資料瞭解網卡啟動不了的原因,今天總結一下幾種網卡啟動不了的解決方案,以備參考。 systemctl restart network //重啟網卡 返回報錯: Restarting network (via systemctl): Job for network.service faile ...
  • win10自帶郵箱如何使用? 相信很多小伙伴在登錄win10自帶的郵箱登錄QQ郵箱時,顯示同步失敗或者登錄超時,但又找不到相關的資料,下麵是我自己郵箱的操作流程,小伙伴可以嘗試一下,有什麼問題留言即可 一、準備工作: 登錄網頁版QQ郵箱,設置→賬戶→找到“POP3/IMAP/SMTP/Exchang ...
  • hp proliant sl210t伺服器,一般都會帶有兩個陣列卡 一個伺服器自帶的Dynamic Smart Array B120i RAID控制器,一個為Slot卡槽上的Smart Array P420控制器 這裡我們使用Smart Array P420對伺服器的磁碟進行raid 1類型的陣列配 ...
  • 今天碰到個負載高引起的問題但是查看zabbix監控並沒有報警,檢查後發現監控取值與實際伺服器內負載不一致。 解決方法 修改zabbix模板Template OS Linux找到 Processor load (1 min average per core)修改key把 system.cpu.load ...
  • 一.介紹安裝 公司由於linux雲伺服器還沒批下來,暫時先在windows伺服器上測試。Windows版nginx使用本地Win32 API(而非Cygwin模擬層)。當前僅使用select()和poll()(1.15.9)連接處理方法(事件驅動模型),因此不應期望高性能和可伸縮性(在linux上支 ...
  • 參考穀粒學院的linux視頻教程:http://www.gulixueyuan.com/course/300/task/7091/show ...
  • CPU主要功能:處理指令、執行操作、要求進行動作、控制時間、處理數據。 結合資料庫實例CPU占用高,可能的原因是資料庫在執行大量的操作(全表查詢、大量排序等)。 由於公司沒有DBA,遇到資料庫問題只能自己排查。 一、是否存在死鎖 查詢死鎖以及解鎖的語句參考下方: 查看死鎖ID 查看死鎖ID SELE ...
  • 摘要: 下文講述在sqlserver資料庫中,將日期數據轉換為指定格式的方法分享,如下所示; 實驗環境:sqlserver 2008 R2 實現思路: 實現方法1: 使用year函數和month函數獲取相應的數值,然後採用字元串拼接的方法輸出相應的數據 實現方法2: CONVERT(varchar( ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...