我需要将顺序增加的id分配给一组名称。这归结为:
包含要生成的下一个ID的字段:curId
包含名称/值对的集myset
,其中值为id,名称为名称
问题:
我需要原子地:
1.检查myset
是否包含' name'。如果没有,
2.使用$ inc生成新的id
3.在myset中插入名称/ ID对。
我无法在mongodb中找到一种方法,至少在没有引入竞争条件的情况下。建议欢迎。
更新
示例文档(它应该是什么样子)。
在添加' c':
之前{
"mySet": [
{
"name": 'a',
"value" : 1
},
{
"name": 'b',
"value" : 2
}
]
}
添加' c'。返回3,因为这是分配给' c'。
的ID{
"mySet": [
{
"name": 'a',
"value" : 1
},
{
"name": 'b',
"value" : 2
},
{
"name": 'c',
"value" : 3
}
]
}
尝试添加' c'再次。 没有任何事情发生,因为' c'已经存在了。但是' 3'返回,因为这是' c'。
的ID答案 0 :(得分:1)
这是一种简单的方法,它涉及维护与nextId相对应的计数器 in 使用此集合的文档,它涉及一个简单的查找查询和更新。从空文档开始:
{
"curId": 1,
"mySet" : [ ]
}
想要添加下一个"名称"的过程(变量名称)执行以下两个操作:
var Name = "a";
var curId = db.coll.findOne({"mySet.name":{"$ne":Name}},{"_id":0,"curId":1}).curId;
/* curId variable is now 1 */
var result = db.coll.update(
{ "mySet.name" : {"$ne":Name}, "curId":curId },
{ "$push": {"mySet" : {"name":Name,"value":curId} }, "$inc":{"curId":1} }
);
if (result.nModified == 0) {
print("We lost - someone else must have gotten there first");
}
这里的关键部分是:
查找查询和更新查询的条件是Name
尚未进入mySet
数组"名称"。
更新查询还包含先前读取的curId
值,以确保自我们阅读以来没有其他线程更新过该记录。
curId
字段仅在成功$push
时增加到数组而不是上一次读取curId
- 直到我们成功使用{ {1}}值可用,我们不想增加它。
答案 1 :(得分:0)
db.counter.insert({"_id": "myCollectionName", "count": 1})
这会创建一个计数器集合。运行查找并修改以增加它。 http://docs.mongodb.org/manual/reference/method/db.collection.findAndModify/此操作是原子操作,不会导致竞争条件。将结果用作新ID。
编辑:道歉,没有意识到所有3个都需要是原子的。使用$ push(http://docs.mongodb.org/manual/reference/operator/update/push/)。此操作不保证数组将按顺序排列(id为2可能会在id 1之前将其放入数组中)但是,如果您使用直接更新而丢失数组元素的可能性是不存在的。使用$ push与findandmodify(http://docs.mongodb.org/manual/reference/method/db.collection.findAndModify/)结合使用,这也是原子的。