在 MongoDB 中存储 null 与根本不存储密钥
Posted
技术标签:
【中文标题】在 MongoDB 中存储 null 与根本不存储密钥【英文标题】:Storing null vs not storing the key at all in MongoDB 【发布时间】:2012-09-06 08:42:12 【问题描述】:在我看来,当您创建 Mongo 文档并有一个字段 key: value
有时不会有值时,您有两种选择:
-
写入
key: null
,即在字段中写入空值
根本不要将密钥存储在该文档中
这两个选项都很容易查询,其中一个查询key : null
,另一个查询key : $exists : false
。
我真的想不出这两个选项之间有什么区别会对应用场景产生任何影响(除了选项 2 的存储空间稍少)。
谁能告诉我是否有任何理由让人们更喜欢这两种方法中的任何一种,为什么?
编辑
在问了这个问题后,我也想到索引在这两种情况下的行为可能不同,即可以为选项 2 创建一个稀疏索引。
【问题讨论】:
就其价值而言,“稍微减少存储空间”在大规模情况下可能更重要,尤其是当您谈论内存中工作集的大小时。 【参考方案1】:确实,您还有第三种可能性:
key: ""
(空值)
你忘记了关于空值的特殊性。
查询
key: null
将检索所有 key 为 null 或 key不存在的文档。
当$exists:false
上的查询将仅检索字段键不存在的文档时。
要回到您的确切问题,这取决于您的查询和数据代表的内容。 如果您需要保留它,例如,用户设置了一个值然后取消设置它,您应该将该字段保留为 null 或空。如果您不需要,您可以删除此字段。
【讨论】:
我个人会远离 key: " " 因为这暗示它是一个字符串。如果您检索这样一个字段并执行类似 isKeyExists(key) 的操作,即使它是一个空字符串,它也会作为 true 传递。因此,假设您期待一个布尔值,即错误空间。【参考方案2】:请注意,由于 MongoDB 不使用字段名字典压缩,field:null
会消耗磁盘空间和 RAM,而完全不存储 key 不会消耗资源。
【讨论】:
这个答案在 2018 年仍然有效吗? 抱歉回复晚了!我不认为情况仍然如此。启用 WiredTiger 存储和 snappy 压缩后,我认为它应该不会引起注意。【参考方案3】:这真的归结为:
你的场景 您的查询方式 您的索引需要 您的语言我个人选择存储空键。它使集成到我的应用程序中变得更加容易。我将 php 与 Active Record 一起使用,并且 uisng 空值使我的生活变得更加轻松,因为我不必将字段依赖的压力放在应用程序上。此外,我不需要编写任何复杂的代码来处理设置不存在变量的魔法。
我个人不会存储像""
这样的空值,因为如果您不小心,您可能会有两个空值null
和""
,然后您将有一个专门查询的偶然风险时间。所以我个人更喜欢null
用于空值。
至于空间和索引:这取决于有多少行可能没有此列,但我怀疑您是否真的会注意到索引大小的增加是由于一些额外的带有 null 的文档。我的意思是存储方面的差异特别小如果相应的键名也很小。这也适用于大型设置。
坦率地说,我不确定 $exists
和 null
之间的索引使用情况,但是 null
可能是一种更标准化的查询存在的方法,因为请记住 MongoDB 是无模式的,这意味着您不需要拥有文档中的该字段再次产生两个空值:不存在和null
。所以最好选择其中一个。
我选择null
。
【讨论】:
谢谢...但我不相信使用 null 会使应用程序代码更容易(至少在我使用的 C# 驱动程序中没有)。没有复杂的代码,因为在 C# 驱动程序中不存在的键会自动反序列化为 null。 @ZaidMasud 是的,在 C# 以及驱动程序问题中,您有强类型语言。这就是为什么这是一个很难回答的问题,因为所有平台都没有标准,不像 CSS、html 或 OOP 等,这完全取决于你。【参考方案4】:您可能需要考虑的另一点是当您使用诸如 Hibernate OGM 之类的 OGM 工具时。
如果您使用 Java,Hibernate OGM 支持 JPA 标准。因此,如果您可以编写 JPQL 查询,如果您想切换到 OGM 工具支持的备用 NoSQL 数据存储,理论上会很容易。
JPA 没有为 Mongo 中的 $exists 定义等价物。因此,如果您的集合中有可选属性,那么您无法为其编写适当的 JPQL。在这种情况下,如果属性的值存储为 NULL,那么仍然可以编写一个有效的 JPQL 查询,如下所示。
SELECT p FROM pppoe p where p.logout IS null;
【讨论】:
在 MongoDB 中查询 null 包括缺失值。 From official doc: " item : null
查询匹配包含值为空的 item 字段或不包含 item 字段的文档。"
MongoDB 确实支持查询空值,但重点在于与 JPQL 的功能等效性。如果它是一个缺失的属性,就不可能编写一个等效的 JPQL。
我明白了,我只是说我认为SELECT p FROM pppoe p where p.logout IS null;
将在结果中包含缺少的属性。以上是关于在 MongoDB 中存储 null 与根本不存储密钥的主要内容,如果未能解决你的问题,请参考以下文章