【问题标题】:Dealing with mongodb unique, sparse, compound indexes处理mongodb唯一、稀疏、复合索引
【发布时间】:2015-01-28 01:22:08
【问题描述】:

因为mongodb will index sparse, compound indexes that contain 1 or more of the indexed fields,它导致我唯一的稀疏索引失败,因为这些字段之一是可选的,并且为了索引的目的被 mongodb 强制为null

我需要数据库级别的唯一性来确保该字段和其他一些字段的组合,并且必须通过一些连接字符串在应用程序级别进行管理,这让我很担心。

作为替代方案,我考虑将可能为空的索引字段的默认值设置为'null ' + anObjectId,因为它可以让我保留索引而不会导致错误。这看起来像是一个明智的(尽管很老套)的解决方案吗?有谁知道我可以在复合索引上强制执行数据库级唯一性的更好方法?

编辑:我被要求详细说明实际的问题域,所以就这样吧。

我们从客户那里获得大量数据馈送,我们需要将其集成到我们的数据库中。这些提要包括客户提供的各种 (3) 唯一标识符,我们使用这些标识符在数据提要刷新时更新我们存储在数据库中的版本。我需要将这些标识符的唯一性与客户联系起来,因为同一个标识符可能会出现在多个来源中,我们希望允许这样做。

文档结构如下:

{
  "identifiers": {
      "identifierA": ...,
      "identifierB": ...,
      "identifierC": ...
  },
  "client": ...
}

因为每个单独的标识符是可选的(至少需要三个之一),我需要唯一索引索引与客户端的组合(例如一个索引是client加上identifierA的组合) .但是,这个索引必须只有在标识符存在时才会出现,但是我的 mongodb 不支持这个(见上面的超链接)。

我正在考虑上述解决方案,但我想听听其他人是否解决了这个问题或有建议。

【问题讨论】:

  • 太罗嗦,不清楚。尝试发布一些您想要实现的目标的示例。
  • 你能解释一下为什么不清楚吗?我认为我很明确...... 1)我想要多个字段组合的数据库级唯一性保险 2)mongodb 不支持这个 3)我将生成的 objectId 附加到字符串的解决方案有意义吗?
  • 您将其锁定为“向我展示如何创建和索引来做到这一点”和“我认为这是正确的方法,但它不起作用”。我试图给你一个机会来解释你试图通过创建索引来解决的实际问题。因为更了解的人可能知道另一种方式。可能比 hacky 更好?
  • @NeilLunn 查看编辑:)
  • 我可以建议这里的问题是您在子文档中有“键”,而不是说使用带有 [{ "type": "A", "data": "Something },{ "type": "B", "data": "Something else" }] 之类的文档的数组。但这就是我“解释实际问题”的主要意思。如果您更愿意告诉我们您正在存储什么类型的数据、限制是什么以及您是如何使用它的,那么很明显可以看到解决问题的其他方法。

标签: mongodb indexing unique


【解决方案1】:

https://docs.mongodb.org/manual/core/index-partial/

从 mongoDB 3.2 开始,您也可以创建部分索引来支持这一点。

db.users.createIndex(
   { name: 1, email: 1 },
   { unique: true, partialFilterExpression: { email: { $exists: true } } }
)

【讨论】:

  • 实际上,因为我们需要类似的东西: partialFilterExpression: { email: { $exists: true }, email : {$ne: null} } 并且不支持您建议的内容不起作用跨度>
  • 您可以在顶层使用 $and 运算符来支持这一点。能否提供一些错误信息以及 mongo 版本?
  • 您的部分表达式无效。使用 $and: [ {email: { $exists: true} }, email: {$ne: null}}]
  • stackoverflow.com/a/34292680/3343029。你说的对。你可以使用 $type 然后
  • 解决了!谢谢。 TL;DR: $type: "string" 暗示它是一个字符串并且存在,因此它负责处理空值、未定义和不存在的属性
【解决方案2】:

稀疏索引可避免索引不存在的字段。 唯一索引可避免插入具有相同字段值的文档。 不幸的是,从 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 之前检查唯一性。 :-)

【讨论】:

    【解决方案3】:

    hash index 最终就足够了

    【讨论】:

    • 您是如何创建散列复合索引的?
    猜你喜欢
    • 1970-01-01
    • 2013-06-12
    • 1970-01-01
    • 2018-01-22
    • 2015-02-15
    • 2014-12-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多