因为mongodb will index sparse, compound indexes that contain 1 or more of the indexed fields,它导致我的唯一稀疏索引失败,因为其中一个字段是可选的,并且由于mongodb而被强制转换为null
以用于索引。
我需要数据库级别的唯一性保证,以便将此字段与其他一些字段组合在一起,并且必须通过某些串联字符串在应用程序级别管理此问题。
作为替代方案,我考虑将可能为空的索引字段的默认值设置为'null ' + anObjectId
,因为它允许我保留索引而不会导致错误。这看起来像是一个敏感的(虽然是hacky)解决方案吗?有没有人知道我可以在复合索引上强制执行数据库级唯一性的更好方法?
编辑:我被要求详细说明实际的问题域,所以在这里。
我们从客户处获得需要集成到数据库中的大量数据。这些提要包括客户提供的各种(3)唯一标识符,用于更新数据提要刷新时存储在数据库中的版本。我需要将这些标识符的唯一性与客户联系起来,因为相同的标识符可能来自多个来源,我们希望允许这样做。
文档结构如下所示:
{
"identifiers": {
"identifierA": ...,
"identifierB": ...,
"identifierC": ...
},
"client": ...
}
因为每个单独的标识符是可选的(需要三个中的至少一个),所以我需要唯一地索引索引与客户端的组合(例如,一个索引是client
加{{的组合。 1}})。但是,此索引必须仅在标识符存在时发生,但我的mongodb不支持此(请参阅上面的超链接)。
我正在考虑上述解决方案,但我想听听是否其他人已经解决了这个问题或有建议。
答案 0 :(得分:3)
稀疏索引可以避免索引不存在的字段。 唯一索引可以避免插入具有相同字段值的文档。 不幸的是,从MongoDB 2.6.7开始,即使在使用稀疏和唯一属性创建复合索引(索引两个或多个字段)时,也始终强制执行唯一约束。
db = db.connect("test");
db.a.drop();
db.a.insert([
{},
{a : 1},
{b : 1},
{a : 1, b : 1}
]);
db.a.ensureIndex({a:1,b:1}, { sparse: true, unique: true } );
db.a.insert({a : 1}); // throws Error but wanted insert to be valid.
但是,对于具有稀疏和唯一属性的单个索引字段,它可以正常工作。 我觉得这是一个将在未来版本中修复的错误。
无论如何,这里有两个解决这个问题的方法。
1)向每个文档添加一个非空哈希字段,该字段仅在提供用于检查唯一性的所有必需字段时计算。 然后在哈希字段上创建一个稀疏的唯一索引。
function createHashForUniqueCheck(obj){
if( obj.firstName && obj.id){
return MD5( String( obj.firstName) + String(obj.id) );
}
return null;
}
2)在应用程序端,在插入Mongodb之前检查唯一性。 : - )
答案 1 :(得分:0)
hash index最终足以满足此