在密钥名称中的MongoDB点(。)
看来mongo不允许用点(。)或美元符号($)插入键,但是当我使用mongoimport工具导入包含点的JSON文件时,它工作正常。 司机抱怨试图插入该元素。
这是文档在数据库中的样子:
{ "_id": { "$oid": "..." }, "make": "saab", "models": { "9.7x": [ 2007, 2008, 2009, 2010 ] } }
我做这一切都是错误的,不应该像外部数据(即模型)使用哈希映射,或者我可以以某种方式逃避点? 也许我觉得太像JavaScript了。
MongoDB不支持带点的键,所以你必须在导入之前预处理JSON文件来删除/replace它们,否则你将面临各种各样的问题。
这个问题没有一个标准的解决方法,最好的方法是太依赖于具体的情况。 但是,如果可能的话,我会避免使用任何关键的编码器/解码器方法,因为如果JSON重组可能是一次性成本,那么您将继续为此付出不便。
Mongo文档build议replace诸如$
和的非法字符.
与他们的unicode等价物。
在这些情况下,密钥将需要replace保留的$和。 字符。 任何字符都是足够的,但考虑使用Unicode全宽等效项:U + FF04(即“$”)和U + FF0E(即“。”)。
正如在其他答案中提到的MongoDB不允许$
或.
字符作为映射键由于字段名称的限制 。 但是,如美元符号运算符中所述, 转义此限制并不妨碍您使用这些键插入文档,只需更新或查询它们即可。
简单replace的问题.
与[dot]
(如注释中所述)是,当用户合法地要存储密钥[dot]
什么?
Fantom的 afMorphia驱动程序采用的方法是使用类似于Java的Unicode转义序列,但确保任何转义字符都先被转义。 本质上,下面的stringreplace被做(*):
\ --> \\ $ --> \u0024 . --> \u002e
随后从 MongoDB读取映射关键字时进行反向replace。
或在Fantom代码:
Str encodeKey(Str key) { return key.replace("\\", "\\\\").replace("\$", "\\u0024").replace(".", "\\u002e") } Str decodeKey(Str key) { return key.replace("\\u002e", ".").replace("\\u0024", "\$").replace("\\\\", "\\") }
用户需要了解这种转换的唯一时间是构build对这些键的查询。
鉴于通常在数据库中存储dotted.property.names
用于configuration目的,我相信这种方法比简单地禁止所有这样的映射密钥更可取。
(*)afMorphia实际上执行完整/正确的unicode转义规则,正如在Java中的Unicode转义语法中所提到的,但所描述的replace序列也同样适用。
您可以尝试在键中使用散列而不是值,然后将该值存储在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 ] }
之后您将使用哈希访问模型。
var version = "9.7x"; collection.find( { _id : ...}, function(e, data ) { var models = data.models[ md5(version) ]; }
我刚刚实现的一个解决scheme,我非常满意,它涉及将密钥名称和值分成两个单独的字段。 这样,我可以保持字符完全一样,而不用担心任何parsing噩梦。 该文件看起来像:
{ ... keyName: "domain.com", keyValue: "unregistered", ... }
您仍然可以通过在字段keyName 和 keyValue上find
来简单查询。
Lodash对可以让你改变
{ 'connect.sid': 's:hyeIzKRdD9aucCc5NceYw5zhHN5vpFOp.0OUaA6' }
成
[ [ 'connect.sid', 's:hyeIzKRdD9aucCc5NceYw5zhHN5vpFOp.0OUaA6' ] ]
运用
var newObj = _.pairs(oldObj);
我在JavaScript中为每个对象键使用下面的转义:
key.replace(/\\/g, '\\\\').replace(/^\$/, '\\$').replace(/\./g, '\\_')
我喜欢的是它在开始时只replace$
,而不使用在控制台中使用的unicode字符。 _
对我来说比一个unicode字符更可读。 它也不会用另一个(unicode)replace一组特殊字符( $
,。)。 但是正确地逃避与传统\
。
你可以保存它,然后转换成漂亮的
我在Livescript上写了这个例子。 你可以使用livescript.net网站来评估它
test = field: field1: 1 field2: 2 field3: 5 nested: more: 1 moresdafasdf: 23423 field3: 3 get-plain = (json, parent)-> | typeof! json is \Object => json |> obj-to-pairs |> map -> get-plain it.1, [parent,it.0].filter(-> it?).join(\.) | _ => key: parent, value: json test |> get-plain |> flatten |> map (-> [it.key, it.value]) |> pairs-to-obj
它会产生
{"field.field1":1, "field.field2":2, "field.field3":5, "field.nested.more":1, "field.nested.moresdafasdf":23423, "field3":3}
一个迟到的答案,但如果你用Mongo的用户,它可以pipe理你的转换。 这是JohnnyHK的解决scheme,但由Spring处理。
@Autowired private MappingMongoConverter converter; @PostConstruct public void configureMongo() { converter.setMapKeyDotReplacement("xxx"); }
如果你存储的Json是例如
{ "axxxb" : "value" }
通过Spring(MongoClient)它将被读作
{ "ab" : "value" }
/home/user/anaconda3/lib/python3.6/site-packages/pymongo/collection.py
在错误消息中find它。 如果你使用anaconda
(如果没有find对应的文件),只需在上面的文件check_keys = True
的值改为False
。 这将工作!