问题描述
说我们目前有两个集合: Teachers
和 Students
,我们限制每个老师最多只能拥有 30 个学生,当然我有已经在每个文档上设置了一个参考键,例如 studentsId
, teachersId
.
Says we currently have two collections: Teachers
and Students
, we limit each teacher can only owns up to 30 students, surely I have already set a reference-key like studentsId
, teachersId
on each document.
当我要创建一个新学生时,如何确保仅在指定的老师少于30名学生时创建它?
When I'm about to create a new Student, how can I make sure I only create it when the specify teacher has less than 30 students?
// get students count under specify teacher
const StudentNums = await Teachers.findById(1234).studentsId.length;
if (StudentNums < 30) /* create student */
(以上代码是用JS编写的)
(above code is written JS)
毫无疑问,以上代码在并发时会失败,导致mongodb共享读取锁,有什么想法吗?提前发短信.
undoubtedly above code would fail when concurrency, cause mongodb share read locks, any ideas? tks in advance.
推荐答案
为什么不处理与并发相关的任何事情,为什么不仅仅检查您的老师是否可以容纳更多学生呢?您可以通过一次操作进行检查和更新,以确保原子性.
Instead of handling anything related to concurrency, why not just check if your teacher can accomodate any more students ? You can check and update in a single operation to ensure atomicity.
本质上可以归结为在查找查询中添加学生长度检查,如下所示:
It essentially boils down to adding student length check in find query like below :
teachers.update({id: 1, '$where': 'this.students.length < 8'}, {'$push': {students: 8}}
在下面添加了一个测试用例:
Added a test case below:
const mongodb = require('mongodb')
const mongoClient = mongodb.MongoClient
mongoClient.connect('mongodb://localhost:27017/stackoverflow', function (err, db) {
if (err) {
console.log(`DB connect error ${JSON.stringify(err)}`)
} else {
const teachers = db.collection('teachers')
let doc = {id: 1, name: 'Ms Anderson', students: [1, 2, 3, 4, 5, 6, 7], subject: 'Matrix'}
teachers.insert(doc, {w: 1}, function (err, result) {
console.log(`insert error ${JSON.stringify(err)}`)
console.log(`insert result : ${JSON.stringify(result)}`)
//Check the $where parameter, it will return only if student array has size less than 8
teachers.update({id: 1, '$where': 'this.students.length < 8'}, {'$push': {students: 8}}, {w: 1}, function (err, result) {
console.log(`update error ${JSON.stringify(err)}`)
console.log(`update result : ${JSON.stringify(result)}`)
})
})
}
})
如果文档已更新,则
结果
为1,否则为0.
result
is 1 if document is updated else 0.
这篇关于mongodb并发插入文档的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!