2014-01-08 59 views
1

问题:我在mongo中创建一个friend_requests集合,并且我想在两个用户标识之间强制实现一个唯一键(比方说我为了参数而拥有一个“from_user”和“to_user”键/列)。但是经过测试,我发现唯一性只能在一个方向上执行。MongoDB:双面唯一键约束

 

当前 “纲要”

这里是我的指标:

> 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" } 

 

解决方案

首选的解决方案将不依赖管理代码来检查的独特性,但是如果IM是正确的,有没有办法告诉蒙戈在内部做到这一点。所以我想下一个最好的事情就是尽可能轻量级的管理代码。

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

很明显,解决方案是基于mysql的思想,具有递增的整数ID。 Mongo ID不是整数,所以我假设没有真正的“小”ID?

 

脚注:我完全新的蒙戈,所以我可能只是进行一些严重愚蠢的数据库设计错误。

在此先感谢您的任何建议。

回答

0

如果你能指标的值,它必须是well-ordered,这样你就可以比较任意两个可转位密钥,即使他们是ObjectId类型,UUID等,所以总是在特定领域的存储较低的值的方法作品。

但是,确保比较始终如一是非常重要的。例如,比较可能会转换为字符串并比较字符串。或者,也可以选择直接比较字节,这会在小端和大端机器上产生不同的结果。

0

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

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

然后,在{ user1 : 1, user2 : 1 }创建uniquecompound索引来强制所需的唯一性约束。

或者,如果您想维护有关哪个用户发起好友请求的信息,请考虑添加第三个字段以强制实现唯一性。下面的模式创建文档:

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

应用程序可以将两者连接起来的用户ID和存储在req_key领域,确保最低的用户ID是第一位的。然后,在{ req_key : 1 }上添加唯一索引。