在密钥名称中的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 keyValuefind来简单查询。

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 。 这将工作!