mongdb确保两种方式的唯一性

时间:2018-10-18 03:12:42

标签: mongodb indexing unique-index

说我有ab字段。我想拥有一个复合唯一性,如果a: 1, b: 2,我将无法做a: 2, b: 1

我想要这样做的原因是因为我正在创建“朋友列表”类型的集合,如果a连接到b,那么它也将自动反向。

这是在模式级别上实现的吗?还是我需要执行查询以进行检查。

2 个答案:

答案 0 :(得分:1)

如果您不需要区分请求者和被请求者,则可以在保存或查询之前对值进行排序,以使两个ab字段对任何一对朋友具有可预测的顺序ID(并且您可以利用唯一索引约束)。

例如,使用mongo shell:

  • 创建一个帮助函数,以可预测的顺序返回朋友对:

    function friendpair (friend1, friend2) {
        if ( friend1 < friend2) {
            return ({a: friend1, b: friend2})
        } else {
            return ({a: friend2, b: friend1})      
        }
    }
    
  • 添加复合唯一索引:

    > db.friends.createIndex({a:1, b:1}, {unique: true});
    {
        "createdCollectionAutomatically" : true,
        "numIndexesBefore" : 1,
        "numIndexesAfter" : 2,
        "ok" : 1
    }
    
  • 插入唯一对(应该起作用)

    > db.friends.insert(friendpair(1,2))
    WriteResult({ "nInserted" : 1 })
    
    > db.friends.insert(friendpair(1,3))
    WriteResult({ "nInserted" : 1 })
    
  • 插入非唯一对(应返回重复的密钥错误):

    > db.friends.insert(friendpair(2,1))
    WriteResult({
        "nInserted" : 0,
        "writeError" : {
            "code" : 11000,
            "errmsg" : "E11000 duplicate key error collection: test.friends index: a_1_b_1 dup key: { : 1.0, : 2.0 }"
        }
    })
    
  • 搜索应按以下两种顺序进行:

    db.friends.find(friendpair(3,1)).pretty()
    { "_id" : ObjectId("5bc80ed11466009f3b56fa52"), "a" : 1, "b" : 3 }
    
    db.friends.find(friendpair(1,3)).pretty()
    { "_id" : ObjectId("5bc80ed11466009f3b56fa52"), "a" : 1, "b" : 3 }
    
  • 您也可以将findAndModifyupsert一起使用,而不是处理重复的键错误或插入与更新,因为这应该是唯一的对:

    > var pair = friendpair(2,1)
    > db.friends.findAndModify({
        query: pair,
        update: {
            $set: {
                a : pair.a,
                b : pair.b
            },
            $setOnInsert: { status: 'pending' },
        },
        upsert: true
    })
    
    {
        "_id" : ObjectId("5bc81722ce51da0e4118c92f"),
        "a" : 1,
        "b" : 2,
        "status" : "pending"
    }
    

答案 1 :(得分:0)

您似乎无法对整个数组的值进行唯一处理,因此我正在做一种变通方法。我正在使用Launch agent via Java Web Start,如下所示:

$jsonSchema

然后,我将使用{ $jsonSchema: { bsonType: "object", required: [ "status", "users" ], properties: { status: { enum: [ "pending", "accepted" ], bsonType: "string" }, users: { bsonType: "array", description: "references two user_id", items: { bsonType: "objectId" }, maxItems: 2, minItems: 2, }, } } } 查找已连接的用户,例如

$all