如何将数组值插入现有的 JSON 文档?
Posted
技术标签:
【中文标题】如何将数组值插入现有的 JSON 文档?【英文标题】:How to insert an array value to an existing JSON document? 【发布时间】:2021-12-13 14:29:49 【问题描述】:给定一个包含 JSON 文档的列,我可以使用 JSON_SET()
将 JSON 文档中的键设置为值。支持的值为null
、true
、false
、数字和字符串;但我不知道如何设置数组。
example in the documentation(对于JSON_INSERT()
,但它的工作原理相同)奇怪地显示了一个天真的用户可能会如何尝试设置数组值而失败,但是有点灯罩它;如果你仔细观察你会发现这个数组被转换成了一个字符串。
我想出了一个你第一次使用的解决方法:
JSON_SET(col, '$.field', "first value")
-- "field": "first value"
然后:
JSON_ARRAY_APPEND(col, '$.field', "second value")
-- "field": ["first value", "second value"]
但是这样做有各种各样的问题,最重要的是它不能用于设置少于2个值的数组。
【问题讨论】:
【参考方案1】:JSON_INSERT/JSON_REPLACE/JSON_SET
很乐意接受 JSON 文档作为 值:
SELECT JSON_INSERT('"foo": "bar"', '$.new', JSON_ARRAY('one', 'two', 'three'))
/*
"foo": "bar",
"new": ["one", "two", "three"]
*/
注意:
JSON_SET()
替换现有值并添加不存在的值。
JSON_INSERT()
插入值而不替换现有值。
JSON_REPLACE()
仅替换现有值。
如果您想将值附加到可能/可能不存在的数组中,请按以下顺序链接函数:
SELECT JSON_ARRAY_APPEND(JSON_INSERT('"foo": "bar"', '$.new', JSON_ARRAY()), '$.new', 'four')
/*
"foo": "bar",
"new": ["four"]
*/
SELECT JSON_ARRAY_APPEND(JSON_INSERT('"foo": "bar", "new": ["one", "two", "three"]', '$.new', JSON_ARRAY()), '$.new', 'four')
/*
"foo": "bar",
"new": ["one", "two", "three", "four"]
*/
【讨论】:
哇。这一点都不明显:select JSON_ARRAY("a", "b"); -- > ["a", "b"]
和 select JSON_SET('"foo":"bar"', '$.baz', '["a", "b"]'); -- > '"foo": "bar", "baz": "[\"a\", \"b\"]"'
但 select JSON_SET('"foo":"bar"', '$.baz', JSON_ARRAY("a", "b")); -- > '"foo": "bar", "baz": ["a", "b"]'
是的。 '[1, 2]'
看起来像 JSON,但它仍然是一个字符串,就像 'whatever'
。使用来自Functions That Create JSON Values 的函数之一,它返回 JSON 数据类型。
另一个重要的注意事项,我多次撞到我的头 - 至少在 MariaDB 中,JSON_*
函数在它们只是返回 NULL
而不是抛出错误的情况下更失败,所以如果在 UPDATE
语句中使用它们,建议将它们包装在 IFNULL()
中 - 像这样:UPDATE table SET col = IFNULL(JSON_ARRAY_APPEND(col, '$.key', 'val'), col) ...
您可以在执行此类查询后使用SHOW WARNINGS
来识别损坏的 JSON 并进行修复。
问题是“损坏的JSON”通常是数据库中完全有效的JSON。例如,JSON_REPLACE('','$.foo','bar')
正确返回
,但 JSON_ARRAY_APPEND('','$.foo','bar')
返回 NULL
,这可能令人惊讶,如果您在 UPDATE
语句中盲目使用它 - 您只是丢失了一些数据并可能导致任何未来操作失败。以上是关于如何将数组值插入现有的 JSON 文档?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 pymongo 将新的值数组附加到 mongodb 中的现有数组文档?