该
函数用于修改集合中的文档,类似于 SQL 数据库的UPDATE语句。它以搜索条件字符串 ( SearchConditionStr ) 作为参数来指定要修改的文档——关于
SearchConditionStr的详细讨论可以在
第 4.3.2 节“Collection.find()”中找到。
modify(
SearchConditionStr
)
如果一个或多个文档与搜索条件字符串匹配,则它们将被链接在该方法之后的任何这些方法修改modify()
。它们可以一个接一个地链接多次:
-
set("
: 将文档路径 ( DocPath ) 表达式匹配的元素设置为表达式或文字 ( ExprOrLiteral ) 表达式表示的值。DocPath
",ExprOrLiteral
)DocPath 表达式是一种JSON 路径表达式,用于标识 函数找到的文档中的一个或多个 JSON 元素。请参阅第 4.3.2 节“Collection.find()”中关于 JSON 路径的 讨论。如果DocPath指定的元素不存在,它将作为新元素添加到文档中。
modify()
ExprOrLiteral 指定要为 DocPath表示的元素设置的值。它可以是以下任何一项:
文字值。例如,10 或“约翰”。
-
任何 X DevAPI Expression,包装在
expr()
函数中(或mysql.expr()
用于 MySQL Shell 和一些连接器),因此它不会被视为文字值。以下是一些示例,它们并未穷尽使用 for ExprOrLiteral的可能性:mysql.expr(Expression)
另一个 DocPath 从正在修改的文档中选择一个值(例如,
set("favorNums[0]", mysqlx.expr("favorNums[1]"))
, 或set("name", mysqlx.expr("$.'last name'"))
.涉及一个或多个 Expression的函数表达式(例如,
set("favorNums[0]", mysqlx.expr("abs(favorNums[1])"))
.一个或多个 Expression由运算符连接(例如,
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
")modify()
用提供的 替换所有匹配的文档json_document
,原始字段除外,_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
该操作遵循 Internet 工程任务组 (IETF) 创建的 JSON 合并补丁的 RFC 7396 规范。下表解释了对字段的操作,这取决于两个文档中的字段状态(注意这是一个递归操作):表 4.1 文档字段的 JSON 补丁合并
原始文档中的字段状态 补丁文档中的字段状态 对原始文档中的字段采取的操作 任意值 值为空 删除字段 值 B 值 A(非空) 如果值 A 或 B 是标量,则将值 B 替换为值 A
如果值 A 和 B 都是 JSON 对象,则使用此表中描述的相同规则合并它们(即,递归地对 JSON 文档应用合并)。
字段不存在 值 A(非空) 添加值为 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(
:将 ExprOrLiteral (参见上面的解释)插入数组中由 DocPath标识的位置,将数组中的任何后续值向右移动。例如:DocPath
,ExprOrLiteral
)arrayInsert("favorNums[1]", 7)
,arrayInsert("favorNums[1]", {even: 2, odd: 3, irrational: 'pi'})
。以下规则适用: -
arrayAppend(
:将由 ExprOrLiteral 表示的值附加到由 DocPath 标识的数组的 末尾。例如,DocPath
,ExprOrLiteral
)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
可以是逗号分隔的列表,也可以是 的数组
。每个都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()
:
# 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"}
另请参阅CollectionModifyFunction
了解 EBNF 中的语法add()
。