如果我尝试添加一些如下所示的 JSON:
{ 'character.treasure_chests': 1 }
Mongoose 会发出这样的错误:
[错误:key character.treasure_chests 不能包含'.']
这是预期的行为吗?
我非常有信心,例如:
{"foo.com": 2}
实际上是有效的 JSON。密钥只是一个字符串。
http://jsonlint.com/ 没有抱怨它,我可以在任何我喜欢的地方愉快地使用它,除非我尝试将它分配给 mongoose 模式(以及其他一些地方)中的 Mixed 属性。
你可以在这个小小提琴中看到它的工作原理:http: //jsfiddle.net/gBgB6/1/
有时,我想通过 keypath {"foo.baz":0} 存储一个值,我想将其用作指向 mongo 文档之外的 javascript 对象中的键的指针。我不想将它以嵌套形式存储在 mongo 中,但我也不想像这样重新映射它
{key:"foo.baz",
value: '0'
}
我想有几次我可能会通过将点(。)映射到另一个字符来将值存储在表中。
在我看来,猫鼬的缺点。我可能会问它:)。
这是一个有效的 JSON,但无效的 Mongoose Schema。由于 Mongoose 的方法允许路径导航,如果你有类似的东西
{
'some.path': 'foo',
'some': {
'path': 'bar'
}
}
如果不是因为这个“缺点”,像document.get('some.path')
这样的方法不知道得到什么。
这并不意味着你永远不能在猫鼬上使用点。您可以将 JSON 分配为一个值:
Schema = new mongoose.Schema({
'some': {
'path': {
'json': {} //any js object
}
}
})
Model = mongoose.model(Schema)
document = new Model()
document.some.path.json = {'inner.data': 'foo'}
Yo 可以通过普通方式访问数据,document.some.path.json['inner.data']
但您将无法使用document.get()
路径参数,'some.path.json'
因为从 Mongoose 的角度来看,此模式路径是终端。您查询此类字段的方式也将受到限制
总而言之,mongoose 文档是基于 JSON 的,但它们不是它的超集。
我也遇到过这个问题,并且在从您几乎无法控制的来源加载数据时也将其视为 PITA。有一些解决方法,请参见下文。
首先,我将假设这些点不在您的架构中,对吗?换句话说,您将此 JSON 作为您无法控制的Mixed类型的一部分插入。如果你想在你的模式中使用点,那是一个完全不同的故事,我会避免这样做。
但是,为了允许 mongoose 处理混合 JSON 中的点键,您至少可以做两件事:
正如其他人所建议的那样,只需将点替换为另一个字符或字符序列(例如-
or )来转义它们-DOT-
。当然,这确实意味着,如果您必须映射回原始数据,并且需要将-
or替换-DOT-
为常规.
,您必须确保原始数据中没有任何-
' 或-DOT-
'这也将被替换......此外,它在您的数据库层前面添加了一个预处理步骤,我尽可能避免这样做。
我实际上注意到猫鼬只在创建新对象时抱怨这一点,如下所示:
let foo = new Foo({ data: {'character.treasure_chests': 1 }});
foo.save(); // results in Error: key character.treasure_chests must not contain '.'
但是,当您更新现有文档时,它似乎并没有抱怨点:
let foo = new Foo({ data: {}});
await foo.save(); // first save the new object
foo.data = {'character.treasure_chests': 1 };
foo.save(); // no errors when updating the existing object!
当然,为此您需要对数据库进行 2 次调用,从而使插入复杂性有效地加倍,但至少您在 mongodb 中有点键!
请注意,这也可能对您查询这些键的方式产生影响。但是由于这种类型的数据通常是混合类型的,所以无论如何您都不能在那里进行太多的结构化查询。