Mic*_*aev 72 javascript mongodb nosql
似乎mongo不允许插入带点(.)或美元符号($)的键,但是当我使用mongoimport工具导入包含点的JSON文件时,它工作正常.司机抱怨试图插入该元素.
这是文档在数据库中的样子:
{
"_id": {
"$oid": "..."
},
"make": "saab",
"models": {
"9.7x": [
2007,
2008,
2009,
2010
]
}
}
Run Code Online (Sandbox Code Playgroud)
我这样做是错误的,不应该使用像外部数据那样的哈希映射(即模型),还是可以以某种方式逃避点?也许我在想类似Javascript.
Joh*_*yHK 63
MongoDB不支持带有点的键,因此您必须预先处理JSON文件以在导入之前删除/替换它们,否则您将为各种各样的问题做好准备.
这个问题没有标准的解决方法,最好的方法太依赖于具体情况.但是如果可能的话,我会避免使用任何关键的编码器/解码器方法,因为你将继续为永久性付出不便,因为JSON重组可能是一次性成本.
Mar*_*cny 18
该蒙戈文档建议替换非法字符,如$
和.
他们的Unicode的等价物.
在这些情况下,密钥需要替换保留的$和.字符.任何字符都足够了,但考虑使用Unicode全宽等价:U + FF04(即"$")和U + FF0E(即".").
Ste*_*non 17
正如其他答案中所提到的,由于字段名称的限制, MongoDB不允许$
或.
字符作为映射键.但是,如美元符号运算符中所述,转义此限制并不会阻止您插入具有此类键的文档,它只会阻止您更新或查询它们.
简单地更换问题.
与[dot]
(如在评论中提到),当用户合法想要存储密钥,会发生什么U+FF0E
?
该办法魅影的 afMorphia驱动程序需要的是用类似的Java的Unicode转义序列,但要确保任何转义字符转义第一.本质上,进行以下字符串替换(*):
\ --> \\
$ --> \u0024
. --> \u002e
Run Code Online (Sandbox Code Playgroud)
随后从 MongoDB 读取映射键时进行反向替换.
或者在Fantom代码中:
Str encodeKey(Str key) {
return key.replace("\\", "\\\\").replace("\$", "\\u0024").replace(".", "\\u002e")
}
Str decodeKey(Str key) {
return key.replace("\\u002e", ".").replace("\\u0024", "\$").replace("\\\\", "\\")
}
Run Code Online (Sandbox Code Playgroud)
用户需要了解此类转换的唯一时间是构造对此类密钥的查询.
鉴于[dot]
出于配置目的而存储在数据库中是很常见的,我认为这种方法比简单地禁止所有这样的映射键更可取.
(*)afMorphia实际上执行完整/正确的unicode转义规则,如Java中的Unicode转义语法中所述,但所描述的替换序列也可以正常工作.
h4c*_*k3d 11
MongoDB的最新稳定版本(v3.6.1)现在支持键或字段名称中的点(.).
Ste*_*eve 10
我刚刚实现的解决方案,我真的很满意,涉及将密钥名称和值拆分为两个单独的字段.这样,我可以保持角色完全相同,而不用担心任何解析噩梦.该文档看起来像:
{
...
keyName: "domain.com",
keyValue: "unregistered",
...
}
Run Code Online (Sandbox Code Playgroud)
您仍然可以通过find
对字段keyName 和 keyValue执行a 来轻松查询.
所以代替:
db.collection.find({"domain.com":"unregistered"})
Run Code Online (Sandbox Code Playgroud)
哪个实际上不会按预期工作,你会运行:
db.collection.find({keyName:"domain.com", keyValue:"unregistered"})
Run Code Online (Sandbox Code Playgroud)
它将返回预期的文件.
您可以尝试在键中使用散列而不是值,然后将该值存储在JSON值中.
var crypto = require("crypto");
function md5(value) {
return crypto.createHash('md5').update( String(value) ).digest('hex');
}
var data = {
"_id": {
"$oid": "..."
},
"make": "saab",
"models": {}
}
var version = "9.7x";
data.models[ md5(version) ] = {
"version": version,
"years" : [
2007,
2008,
2009,
2010
]
}
Run Code Online (Sandbox Code Playgroud)
然后,您将使用散列访问模型.
var version = "9.7x";
collection.find( { _id : ...}, function(e, data ) {
var models = data.models[ md5(version) ];
}
Run Code Online (Sandbox Code Playgroud)
现在支持
MongoDb 3.6以后的字段名称支持点和美元。请参阅以下 JIRA:https : //jira.mongodb.org/browse/JAVA-2810
将您的 Mongodb 升级到 3.6+ 听起来是最好的方法。
你需要逃脱钥匙。由于似乎大多数人不知道如何正确转义字符串,因此步骤如下:
另外,请记住 mongo 也不允许键以“$”开头,因此您必须在那里执行类似的操作
这是一些执行此操作的代码:
// returns an escaped mongo key
exports.escape = function(key) {
return key.replace(/~/g, '~s')
.replace(/\./g, '~p')
.replace(/^\$/g, '~d')
}
// returns an unescaped mongo key
exports.unescape = function(escapedKey) {
return escapedKey.replace(/^~d/g, '$')
.replace(/~p/g, '.')
.replace(/~s/g, '~')
}
Run Code Online (Sandbox Code Playgroud)