在我看来,当你创建一个Mongo文档并且有一个有时没有值的字段{key, value}
时,你有两个选择:
{key, null}
,即在字段这两个选项都很容易查询,您可以查询{key : null}
,另一个查询{key : {$exists : false}}
。
我无法想到在应用程序场景中会产生任何影响的两个选项之间的任何差异(除了选项2的存储量略少)。
任何人都可以告诉我,如果有任何理由,你会更喜欢这两种方法中的任何一种,为什么?
修改
在询问问题后,我也发现索引在两种情况下的行为可能不同,即可以为选项2创建稀疏索引。
答案 0 :(得分:34)
的确,你还有第三种可能性:
key: ""
(空值)
你忘了关于空值的特殊性。
查询
key: null
将检索密钥为空的所有文档或,其中密钥不存在。
当$exists:false
上的查询只检索不存在字段键的文档时。
要回到您的确切问题,这取决于您的查询和数据代表什么。 如果你需要保留它,例如,用户设置一个值然后取消设置它,你应该将该字段保持为null或为空。如果您不需要,可以删除此字段。
答案 1 :(得分:16)
请注意,由于MongoDB不使用字段名字典压缩,field:null
会占用磁盘空间和RAM,而根本不存储密钥也不会消耗资源。
答案 2 :(得分:7)
这真的归结为:
我个人选择存储空键。它使我可以更轻松地集成到我的应用程序中。我使用PHP与Active Record和uisng null值使我的生活变得更加容易,因为我不必在应用程序上加上字段加速的压力。此外,我不需要制作任何复杂的代码来处理魔法来设置不存在的变量。
我个人不会存储像""
这样的空值,因为如果你不小心你可以有两个空值null
和""
,那么你就会有一个危险的时间特别查询。所以我个人更喜欢null
为空值。
至于空间和索引:它取决于有多少行可能没有这个列但我怀疑你会真正注意到由于一些额外的文档带有null而导致索引大小增加。我的意思是存储的差异是特别是如果相应的键名也很小。这也适用于大型设置。
我坦率地不确定$exists
和null
之间的索引使用情况,但null
可能是一种更标准化的方法来查询存在,因为记住MongoDB是无模式的,这意味着你没有要求在doc中再生成两个空值的字段:non-existant和null
。最好选择其中一种。
我选择null
。
答案 3 :(得分:2)
您可能需要考虑的另一点是使用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;