无法将带有点的键(键路径)添加到具有以下类型的 Mongoose 字段:Schema.Types.Mixed

Posted

技术标签:

【中文标题】无法将带有点的键(键路径)添加到具有以下类型的 Mongoose 字段:Schema.Types.Mixed【英文标题】:Can't add keys with dots (key paths) to a Mongoose field with type: Schema.Types.Mixed 【发布时间】:2013-06-29 07:40:08 【问题描述】:

如果我尝试添加一些如下所示的 JSON:

 'character.treasure_chests': 1 

Mongoose 发出类似这样的错误叫声:

[错误:key character.treasure_chests不能包含'.']

这是预期的行为吗?

【问题讨论】:

mongo dot notation ambiguity的可能重复 【参考方案1】:

我非常有信心:

"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'
 

我想有几次我可能会通过将点 (.) 映射到另一个字符来将值存储在表中。

在我看来,猫鼬有一个缺点。我可能会问它:)。

【讨论】:

【参考方案2】:

这是一个有效的 JSON,但无效的 Mongoose 架构。由于 Mongoose 的方法允许路径导航,如果你有类似的东西


  'some.path': 'foo',
  'some': 
    'path': 'bar'
  

如果不是因为这个“缺点”,document.get('some.path') 这样的方法不知道会得到什么。

这并不意味着你永远不能在 mongoose 中使用点。您可以将 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'

你可以通过普通的 document.some.path.json['inner.data'] 访问数据,但你不能使用 document.get() 和比 'some.path.json' 更远的路径参数,因为从 Mongoose 的角度来看这个 模式路径 是终端.您查询此类字段的方式也会受到限制

所有 mongoose 文档都是基于 JSON 的,但它们不是它的超集。

【讨论】:

【参考方案3】:

我也遇到过这个问题,当从您几乎无法控制的来源加载数据时,也将其视为 PITA。有一些解决方法,请参见下文。

首先,我假设这些点不在您的架构中,对吧?换句话说,您将此 JSON 作为您无法控制的 Mixed 类型的一部分插入。如果您想在架构中使用点,那就完全不同了,我会避免这样做。

为了让 mongoose 处理混合 JSON 中的点键,您至少可以做两件事:

    替换字符

正如其他人所建议的,只需将点替换为另一个字符或字符序列(例如 --DOT-)即可将它们转义。当然,这确实意味着如果您必须映射回原始数据,并且需要将 --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 中有点键!

请注意,这可能还会影响您查询这些键的方式。但是由于这种类型的数据通常是混合类型的,所以无论如何您都不能在那里进行太多的结构化查询。

【讨论】:

【参考方案4】:

是的,是的。据我所知,有效的 JSON 没有点。 你应该做的是:


  "character": 
    "treasure_chests": 1
  

这里是一个例子:JSON Schema example

【讨论】:

以上是关于无法将带有点的键(键路径)添加到具有以下类型的 Mongoose 字段:Schema.Types.Mixed的主要内容,如果未能解决你的问题,请参考以下文章

如何为具有不同数量的键/值对的对象添加类型? [关闭]

如何将重复键添加到字典中

字典使所有键的值等于最近的键/值添加

向PYTHON列表中的键添加值

如何根据散列中的键/值查找键/值数据并将其添加到 Redis 中的散列?

快速,在具有复合谓词的提取结果控制器中找不到实体的键路径