文件首頁
X DevAPI 使用者指南
下載本手冊
PDF (美式信紙) - 1.4MB
PDF (A4) - 1.4MB


X DevAPI 使用者指南  /  ...  /  Collection.modify()

4.3.3 Collection.modify()

modify(SearchConditionStr) 函式用於修改集合中的文件,類似於 SQL 資料庫的 UPDATE 陳述式。它接受搜尋條件字串 (SearchConditionStr) 作為參數,以指定要修改的文件—關於 SearchConditionStr 的詳細討論,請參閱 第 4.3.2 節,〈Collection.find()〉

如果搜尋條件字串符合一個或多個文件,則會使用在 modify() 方法之後鏈結的任何這些方法來修改這些文件。它們可以一個接一個地鏈結,而且可以鏈結多次

注意事項
  • 文件的 _id 無法使用以下方法修改或移除。

  • 對於以下任何以 DocPath 運算式作為其引數之一的方法,適用以下規則

    • DocPath 運算式中,任何包含空格或特殊字元的欄位名稱都必須加上引號;例如,set("name.'last name'", "Smith")unset("name.'last%name'")

    • DocPath 運算式不能包含萬用字元權杖(* 或 **)。

    • DocPath 運算式不能為 Null 或空白。

  • set("DocPath", ExprOrLiteral):使用運算式或常值 (ExprOrLiteral) 運算式表示的值來設定文件路徑 (DocPath) 運算式符合的元素。

    DocPath 運算式是一個 JSON 路徑運算式,用於識別 modify() 函式找到的文件中的一個或多個 JSON 元素。請參閱第 4.3.2 節,〈Collection.find()〉中關於 JSON 路徑的討論。如果 DocPath 指定的元素不存在,則會將其作為新元素新增至文件中。

    ExprOrLiteral 指定要為 DocPath 表示的元素設定的值。它可以是以下任何一項

    • 常值。例如,10 或 "John"。

    • 任何 X DevAPI 運算式,包裝在 expr() 函式中(或 MySQL Shell 和某些連接器的 mysql.expr()),使其不被視為常值。以下是一些範例,並未窮盡使用 mysql.expr(運算式) 作為 ExprOrLiteral 的所有可能性

      • 另一個 DocPath,從正在修改的文件中選取值(例如,set("favorNums[0]", mysqlx.expr("favorNums[1]"))set("name", mysqlx.expr("$.'last name'")))。

      • 涉及一個或多個 運算式 的函數運算式(例如,set("favorNums[0]", mysqlx.expr("abs(favorNums[1])")))。

      • 由運算子連接的一個或多個 運算式(例如,set("favorNums[0]", mysqlx.expr("favorNums[1]+favorNums[2]+favorNums[3]+3"))set("SameValueOrNot", mysqlx.expr("favorNums[1] = favorNums[2]")))。

      • JSON 文件(例如,set("Greeting", mysqlx.expr("{'season':'winter', 'phrase': 'Happy Holiday'}"))

    注意

    set("$", mysqlx.expr("json_document") 會以提供的 json_document 取代 modify() 符合的所有文件,除了原始 _id 欄位之外,該欄位在文件建立後即無法變更。

  • unset("DocPath[, DocPath] ..."):刪除一個或多個由一個或多個 DocPath 清單表示的欄位或陣列元素(例如,unset("name")unset("name.'last name'", name.'first name'")unset("favorNums[0]"))。

    如果未提供 DocPath,或 DocPath 為 $,則會傳回錯誤(如果您想刪除整個文件,請改用 remove())。

    警告

    請注意,當多個陣列元素被取消設定或刪除時,它們會一個接一個地被移除,因此陳述式中的相同陣列索引對於每個取消設定動作可能指向不同的元素。在移除陣列元素時,請將其納入考量。例如,對於文件

    mysql-js> myColl.find("name = 'Ann'");
    {
        "_id": "00006239f74a0000000000000004",
        "name": "Ann",
        "favorNums": [
            1,
            2,
            3,
            4,
            5
        ]
    }

    以下陳述式並不會像預期那樣移除陣列的第一個和第二個元素

    mysql-js> myColl.modify("name = 'Ann'").unset("favorNums[0]","favorNums[1]");
    Query OK, 1 item affected (0.0038 sec)
    
    mysql-js> myColl.find("name = 'Ann'").fields("favorNums");
    {
        "favorNums": [
            2,
            4,
            5
        ]
    }
    1 document in set (0.0007 sec)

    而是移除陣列的第一個和第三個元素。若要刪除前兩個元素,您可以執行以下操作

    mysql-js> myColl.modify("name = 'Ann'").unset("favorNums[0]","favorNums[0]");
    Query OK, 1 item affected (0.0108 sec)
    
    Rows matched: 1  Changed: 1  Warnings: 0
    mysql-js > myColl.find("name = 'Ann'").fields("favorNums");
    {
        "favorNums": [
            3,
            4,
            5
        ]
    }
    1 document in set (0.0005 sec)

  • patch(Document):對 modify() 符合的任何文件以及作為其參數提供的 JSON Document 執行合併修補。此作業遵循網際網路工程任務組 (IETF) 建立的 JSON 合併修補的 RFC 7396 規格。下表說明欄位的動作,該動作取決於兩個文件中欄位的狀態(請注意,這是一個遞迴作業)

    表格 4.1 文件欄位的 JSON 修補合併

    原始文件中欄位的狀態 修補文件中欄位的狀態 對原始文件中欄位採取的動作
    任何值 值為 Null 移除欄位
    值 B 值 A (非 Null)

    如果值 A 或 B 其中之一是純量,則以值 A 取代值 B

    如果值 A 和 B 都是 JSON 物件,則會使用此表中描述的相同規則合併它們(也就是說,合併會針對 JSON 文件遞迴套用)。

    欄位不存在 值 A (非 Null) 新增欄位,值為 A
    值 C 欄位不存在 欄位無變更

    以下是使用 patch() 合併的簡單範例

    mysql-js> myColl.find("name = 'John Doe'");
    {
        "DOB": "1970-01-01",
        "_id": "0000626028c30000000000000002",
        "name": "John Doe",
        "Phone": 1234567,
        "Standing": "Good",
        "favorNums": {
           "a": 1,
           "b":2 
        }
    }
    1 document in set (0.0009 sec)
     
    mysql-js> myColl.modify("name = 'John Doe'")
        .patch({ name: "Jane Doe", DOB: null, Phone: 9876543, favorNums: { a: 3, b:4 } });
    Query OK, 1 item affected (0.0413 sec)
    
    Rows matched: 1  Changed: 1  Warnings: 0
     
    mysql-js> myColl.find("name = 'Jane Doe'");
    {
        "_id": "0000626028c30000000000000002",
        "name": "Jane Doe",
        "Phone": 9876543,
        "Standing": "Good",
        "favorNums": {
            "a": 3,
            "b": 4
        }
    }
    1 document in set (0.0008 sec)

  • arrayInsert(DocPath, ExprOrLiteral):將一個 ExprOrLiteral(請參閱以上說明)插入到由 DocPath 所識別的位置的陣列中,並將陣列中任何後續的值向右移動。例如:arrayInsert("favorNums[1]", 7)arrayInsert("favorNums[1]", {even: 2, odd: 3, irrational: 'pi'})。適用以下規則

    • 如果 DocPath 沒有識別到陣列元素,則會傳回錯誤。

    • 如果 DocPath 識別到陣列中超出陣列末端的位置,則該值會插入到陣列的末端。

  • arrayAppend(DocPath, ExprOrLiteral):將由 ExprOrLiteral 表示的值附加到由 DocPath 所識別的陣列末端。例如,arrayAppend("favorNums", 555)

    請注意,如果 DocPath 指向一個純量或一個文件值,則該值會自動包裝在一個陣列中,並且由 ExprOrLiteral 表示的值會被新增到該陣列中。例如

    mysql-js> myColl.find("name='Jane Doe'");
    {
        "_id": "000062b0faf90000000000000001",
        "name": "Jane Doe",
        "favorNum": 2
    }
    1 document in set (0.0011 sec)
    
    mysql-js> myColl.modify("name='Jane Doe'").arrayAppend("favorNum",3);
    Query OK, 1 item affected (0.0094 sec)
    
    Rows matched: 1  Changed: 1  Warnings: 0
    mysql-js> myColl.find("name='Jane Doe'");
    {
        "_id": "000062b0faf90000000000000001",
        "name": "Jane Doe",
        "favorNum": [
            2,
            3
        ]
    }
    1 document in set (0.0006 sec)

以下方法可以鏈接到上述的修改方法,以配置修改

  • sort(sortCriteriaList):根據 sortCriteriaList 對要修改的文件排序,sortCriteriaList 可以是一個逗號分隔的列表或一個 sortCriteria 陣列。每個 sortCriteria 都由一個組件名稱和一個搜尋順序(asc 表示遞增,或 desc 表示遞減)組成。例如

    • sort('name asc', 'age desc')

    • sort(['name asc', 'age desc'])

    此方法與 limit() 方法結合使用,以確定要修改哪些符合 modify(SearchConditionStr) 條件的文件。

  • limit(int):將要修改的文件數量限制為 int。當鏈接在 sort() 之後時,只會修改排序列表中前 int 個文件。

這是一個使用 sort().limit() 來限制對文件的修改的示例

mysql-js> myColl.find("name like '%Doe'");
{
    "_id": "000062b0faf90000000000000001",
    "name": "Jane Doe",
    "favorNum": [
        2,
        3
    ]
}
{
    "_id": "000062b372f80000000000000001",
    "name": "Bob Doe",
    "favorNum": [
        1,
        2
    ]
}
{
    "_id": "000062b372f80000000000000002",
    "name": "Mark Doe",
    "favorNum": [
        7,
        8
    ]
}
{
    "_id": "000062b372f80000000000000003",
    "name": "John Doe",
    "favorNum": [
        0,
        4
    ]
}
mysql-js> myColl.modify("name like '%Doe'").unset("favorNum").sort("name asc").limit(2);
Query OK, 2 items affected (0.0082 sec)

Rows matched: 2  Changed: 2  Warnings: 0
mysql-js> myColl.find("name like '%Doe'").sort('name asc');
{
    "_id": "000062b372f80000000000000001",
    "name": "Bob Doe"
}
{
    "_id": "000062b0faf90000000000000001",
    "name": "Jane Doe"
}
{
    "_id": "000062b372f80000000000000003",
    "name": "John Doe",
    "favorNum": [
        0,
        4
    ]
}
{
    "_id": "000062b372f80000000000000002",
    "name": "Mark Doe",
    "favorNum": [
        7,
        8
    ]
}
4 documents in set (0.0068 sec)

也支援使用 bind() 進行參數綁定。execute() 函數會觸發實際執行 modify() 操作。以下範例說明了 modify() 的使用

MySQL Shell JavaScript 程式碼

// Use the collection 'my_collection'
var myColl = db.getCollection('my_collection');

// Add a new document to the collection 
myColl.add({ name:"John Doe", DOB:"1970-01-01", Phone:1234567, Standing: "Good" }).execute();

// Patch the added document, adding, removing, and changing some fields 
myColl.modify("name = 'John Doe'").patch({ name: "Jane Doe", DOB: null, Phone: 9876543, favorNums: [1,2,3,4,5] }).execute();

//Modify fields with different methods
myColl.modify("name like :param").set("Standing", "Bad").bind("param", "J%Doe").execute();
myColl.modify("name like :param").unset("Phone").bind("param", "J%Doe").execute();
myColl.modify("name like :param").arrayInsert("favorNums[1]", 7).bind("param", "J%Doe").execute();
myColl.modify("name like :param").arrayAppend("favorNums", 99).bind("param", "J%Doe").execute();
myColl.modify("name like :param").unset("favorNums[2]").bind("param", "J%Doe").execute();

var doc = myColl.find('name like :param').limit(1).bind('param', 'J%Doe').execute();

print(doc.fetchOne());
/* The output looks like: 
{
    "Standing": "Bad", 
    "_id": "0000626718c10000000000000002", 
    "favorNums": [
        1, 
        7, 
        3, 
        4, 
        5, 
        99
    ], 
    "name": "Jane Doe"
} */

MySQL Shell Python 程式碼

# Use the collection 'my_collection'
myColl = db.get_collection('my_collection')
# Add a new document to the collection 
myColl.add({ "name":"John Doe", "DOB":"1970-01-01", "Phone":1234567, "Standing": "Good" }).execute()

# Patch the added document, adding, removing, and changing some fields 
myColl.modify("name = 'John Doe'").patch({ "name": "Jane Doe", "DOB": None, "Phone": 9876543, "favorNums": [1,2,3,4,5] }).execute()

# Modify fields with different methods
myColl.modify("name like :param").set("Standing", "Bad").bind("param", "J%Doe").execute()
myColl.modify("name like :param").unset("Phone").bind("param", "J%Doe").execute()
myColl.modify("name like :param").array_insert("favorNums[1]", 7).bind("param", "J%Doe").execute()
myColl.modify("name like :param").array_append("favorNums", 99).bind("param", "J%Doe").execute()
myColl.modify("name like :param").unset("favorNums[2]").bind("param", "J%Doe").execute()

doc = myColl.find('name like :param').limit(1).bind('param', 'J%Doe').execute()

print(doc.fetch_one())

# The output looks like:
# {"Standing": "Bad", "_id": "0000626718c10000000000000005", "favorNums": [1, 7, 3, 4, 5, 99], "name": "Jane Doe"}

Node.js JavaScript 程式碼

const mysqlx = require('@mysql/xdevapi');

mysqlx.getSession('mysqlx://127.0.0.1:33060')
    .then(session=> {
        const collection = session.getSchema('mySchema').getCollection('myCollection');
        // Add a new document to the collection 
        return collection.add({ name:"John Doe", DOB:"1970-01-01", Phone:1234567, Standing: "Good" })
          .execute()
          // Patch the added document, adding, removing, and changing some fields 
          .then(()=> {
            return collection.modify("name = 'John Doe'")
              .patch({ name: "Jane Doe", DOB: null, Phone: 9876543, favorNums: [1,2,3,4,5] })
              .execute();
          })
          // Modify fields with different methods
          .then(()=> {
            return collection.modify("name like :param")
              .set("Standing", "Bad")
              .bind("param", "J%Doe")
              .execute();
          })
          .then(()=> {
            return collection.modify("name like :param")
              .unset("Phone").bind("param", "J%Doe")
              .bind("param", "J%Doe")
              .execute();
          })
          .then(()=> {
            return collection.modify("name like :param")
              .arrayInsert("favorNums[1]", 7)
              .bind("param", "J%Doe")
              .execute();
          })
          .then(()=> {
            return collection.modify("name like :param")
              .arrayAppend("favorNums", 99)
              .bind("param", "J%Doe")
              .execute();
          })
          .then(()=> {
            return collection.modify("name like :param")
              .unset("favorNums[2]")
              .bind("param", "J%Doe")
              .execute();
          })
          .then(()=> {
            return collection.find('name like :param')
              .limit(1).bind('param', 'J%Doe')
              .execute();
          })
          .then(res => {
            console.log(res.fetchOne()); 
                     /* The output looks like: 
                       {
                        _id: '00006272fb890000000000000004',
                        name: 'Jane Doe',
                        Standing: 'Bad',
                        favorNums: [ 1, 7, 3, 4, 5, 99 ]
                       } */
           });
    });

C# 程式碼

// Use the collection "my_collection"
var myColl = myDb.GetCollection("my_collection");

// Insert a document
myColl.Add(new { name = "John Doe", DOB = "1970-01-01", Phone = 1234567, Standing = "Good" }).Execute();

//Patch the added document, adding, removing, and changing some fields 
myColl.Modify("name = 'John Doe'")
  .Patch(new { name = "Jane Doe", DOB = (string)null, Phone = 9876543, favorNums = new[] { 1, 2, 3, 4, 5 } })
  .Execute();

//Modify fields with different methods
myColl.Modify("name like :param").Set("Standing", "Bad").Bind("param", "J%Doe").Execute();
myColl.Modify("name like :param").Unset("Phone").Bind("param", "J%Doe").Execute();
myColl.Modify("name like :param").ArrayInsert("favorNums[1]", 7).Bind("param", "J%Doe").Execute();
myColl.Modify("name like :param").ArrayAppend("favorNums", 99).Bind("param", "J%Doe").Execute();
myColl.Modify("name like :param").Unset("favorNums[2]").Bind("param", "J%Doe").Execute();

var docs = myColl.Find("name like :param").Limit(1).Bind("param", "J%Doe").Execute();
Console.WriteLine(docs.FetchOne());

/* The output looks like: 
   {
                  "_id": "00006274151a0000000000000004",
                  "name": "Jane Doe",
                  "Standing": "Bad",
                  "favorNums": [
                    1,
                    7,
                    3,
                    4,
                    5,
                    99
                  ]
                }
*/

Python 程式碼

# Use the collection 'my_collection'
my_coll = my_schema.get_collection('my_collection')

# Add a new document to the collection 
my_coll.add({ "name":"John Doe", "DOB":"1970-01-01", "Phone":1234567, "Standing": "Good" }).execute()

# Patch the added document, adding, removing, and changing some fields 
my_coll.modify("name = 'John Doe'").patch({"name": "Jane Doe", "DOB": None, "Phone": 9876543, "favorNums": [1,2,3,4,5] }).execute()

# Modify fields with different methods
my_coll.modify("name like :param").set("Standing", "Bad").bind("param", "J%Doe").execute()
my_coll.modify("name like :param").unset("Phone").bind("param", "J%Doe").execute()
my_coll.modify("name like :param").array_insert("favorNums[1]", 7).bind("param", "J%Doe").execute()
my_coll.modify("name like :param").array_append("favorNums", 99).bind("param", "J%Doe").execute()
my_coll.modify("name like :param").unset("favorNums[2]").bind("param", "J%Doe").execute()

docs = my_coll.find('name like :param').limit(1).bind('param', 'J%Doe').execute()

print(docs.fetch_one())

# The output looks like:
#{"_id": "0000627ac9ac0000000000000007", "name": "Jane Doe", "Standing": "Bad", "favorNums": [1, 7, 3, 4, 5, 99]}

Java 程式碼

// Use the collection 'my_collection'
Collection myColl = db.getCollection("my_collection");



// Add a new document to the collection 
myColl.add("{ \"name\":\"John Doe\", \"DOB\" : \"1970-01-01\", \"Phone\" : 1234567, \"Standing\" : \"Good\" }").execute();
   
// Patch the added document, adding, removing, and changing some fields 
myColl.modify("name = 'John Doe'").patch("{ \"name\": \"Jane Doe\", \"DOB\" : null, \"Phone\" : 9876543, \"favorNums\" : [1,2,3,4,5] }").execute();

//Modify fields with different methods
myColl.modify("name like :param").set("Standing", "Bad").bind("param", "J%Doe").execute();
myColl.modify("name like :param").unset("Phone").bind("param", "J%Doe").execute();
myColl.modify("name like :param").arrayInsert("favorNums[1]", 7).bind("param", "J%Doe").execute();
myColl.modify("name like :param").arrayAppend("favorNums", 99).bind("param", "J%Doe").execute();
myColl.modify("name like :param").unset("favorNums[2]").bind("param", "J%Doe").execute();

DocResult docs = myColl.find("name like : param").limit(1).bind("param", "J%Doe").execute();

while (docs.hasNext()) {
    DbDoc myDoc = docs.next();
    System.out.println(myDoc);
} 
    
//The output looks like:
//{"Standing":"Bad","_id":"0000627eadcb0000000000000001","favorNums":[1,7,3,4,5,99],"name":"Jane Doe"}

C++ 程式碼

Collection myColl = db.getCollection("my_collection");
          
// Add a new document to the collection 
myColl.add(R"({ "name":"John Doe", "DOB" : "1970-01-01", "Phone" : 1234567, "Standing" : "Good" })").execute();
   
// Patch the added document, adding, removing, and changing some fields 
myColl
  .modify("name = 'John Doe'")
  .patch(R"({
   "name": "Jane Doe", "DOB" : null, "Phone" : 9876543, "favorNums" : [1,2,3,4,5] 
   })")
  .execute();

//Modify fields with different methods
myColl.modify("name like :param").set("Standing", "Bad").bind("param", "J%Doe").execute();
myColl.modify("name like :param").unset("Phone").bind("param", "J%Doe").execute();
myColl.modify("name like :param").arrayInsert("favorNums[1]", 7).bind("param", "J%Doe").execute();
myColl.modify("name like :param").arrayAppend("favorNums", 99).bind("param", "J%Doe").execute();
myColl.modify("name like :param").unset("favorNums[2]").bind("param", "J%Doe").execute();

DocResult docs = myColl.find("name like :param").limit(1).bind("param", "J%Doe").execute();

DbDoc myDoc;
while ((myDoc = docs.fetchOne()))
    {
        cout << myDoc << endl;
    }
    
//The output looks like: 
// {"_id": "0000627ea0a80000000000000006", "name": "Jane Doe", "Standing": "Bad", "favorNums": [1, 7, 3, 4, 5, 99]}

另請參閱 CollectionModifyFunction 以了解 EBNF 中 add() 的語法。