【问题标题】:MongoDB: two-sided unique key constraintMongoDB:双边唯一键约束
【发布时间】:2014-01-08 22:36:21
【问题描述】:

问题:我正在 mongo 中创建一个friend_requests 集合,并且我想在两个用户 ID 之间强制使用唯一键(假设为了参数,我有一个“from_user”和“to_user " 键/列)。但是经过测试,我发现唯一性只在一个方向上强制执行。

 

当前“架构”

这是我的索引:

> db.friend_requests.getIndexes();
[
    {
        "v" : 1,
        "key" : {
            "_id" : 1
        },
        "ns" : "myapp.friend_requests",
        "name" : "_id_"
    },
    {
        "v" : 1,
        "key" : {
            "from_user" : 1,
            "to_user" : 1
        },
        "unique" : true,
        "ns" : "myapp.friend_requests",
        "name" : "from_user_1_to_user_1"
    }
]

这是我的数据证明唯一性是单向的:

> db.friend_requests.find();
{ "_id" : ObjectId("52cd715dcf75451e70450f6e"), "from_user" : "a", "to_user" : "b" }
{ "_id" : ObjectId("52cd741cddf3114c4c501d19"), "from_user" : "b", "to_user" : "a" }

 

解决方案

首选解决方案不依赖管理代码来检查唯一性,但是如果我正确,则无法告诉 mongo 在内部执行此操作。所以我想下一个最好的事情是尽可能轻量级的管理代码。

我为 mysql 实现找到的一个轻量级解决方案是,您始终将最低键存储在第一列(即我的示例中的“from_user”,但如果我显然实现了这个想法,我会称之为“user1”),这样,只要您始终以该格式插入新数据,唯一键约束将始终在需要时触发。这种实现方法的好处是,在查找两个用户之间的现有请求时,您不必同时查找两个变体(即不必检查 1,2 或 2,1,因为它应该始终只是 1,2如果记录存在)。

显然,该解决方案基于 mysql 具有递增整数 id 的想法。 Mongo id 不是整数,所以我假设没有真正的“更小”的 id?

 

脚注:我对 mongo 完全陌生,所以我可能只是犯了一些非常愚蠢的数据库设计错误。

提前感谢您的任何建议。

【问题讨论】:

    标签: mongodb database-design database


    【解决方案1】:

    如果你可以索引一个值,它必须是well-ordered,所以你可以比较任意两个可索引的键,即使它们是ObjectIdUUID等类型,所以总是存储较低的方法特定领域的价值有效。

    但是,确保比较一致地实施很重要。例如,比较可能会转换为字符串并比较字符串。或者,也可以选择直接比较字节,这会导致在 little-endian 和 big-endian 机器上得到不同的结果。

    【讨论】:

      【解决方案2】:

      您提出的解决方案是合理的。使用以下架构创建文档,并确保应用程序始终将最低用户 ID 放在 user1 字段中。

      {
          user1: "a",
          user2: "b",
          ...
      }
      

      然后,在{ user1 : 1, user2 : 1 } 上创建一个unique compound 索引以强制执行所需的唯一性约束。

      或者,如果您想保留有关发起好友请求的用户的信息,请考虑添加第三个字段以强制唯一性。使用以下架构创建文档:

      {
          from_user : "a",
          to_user : "b",
          req_key : "ab",
          ...
      }
      

      应用程序可以连接两个用户 ID 并存储在 req_key 字段中,确保最低的用户 ID 先出现。然后,在{ req_key : 1 } 上添加唯一索引。

      【讨论】:

        猜你喜欢
        • 2011-05-28
        • 2022-01-05
        • 2012-09-02
        • 2017-04-23
        • 2019-01-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-01-01
        相关资源
        最近更新 更多