如何使用聚合确定用户收集了多少积分
How to determine how many points a user has collected using aggregate
我有这个 Schema 结构
const QuizQuestionSchema = new Schema({
course: { type: String, required: true, trim: true },
point: { type: Number, required: true, trim: true, min: 1, max: 20 },
question: { type: String, required: true, trim: true },
codeBoard: { type: String, default: null, nullable: true },
answers: { type: [String], required: true, trim: true },
correctAnswer: { type: String, required: true, trim: true }
});
从客户端我得到文档的数组 ID 和选择的答案 [{id, answer}...]
。
我需要找出用户收集了多少分,比较 correctAnswer 和 answer if match add score。如何使用聚合完成此操作?
例子
客户端
[
{ id: "61bc09994da5e9ffe47fccb9", answer: "1 2 4 3 5" },
{ id: "61bc0af14da5e9ffe47fccbb", answer: "1 4 3 2" },
...
];
服务器文件
{
_id: new ObjectId("61bc09994da5e9ffe47fccb9"),
course: 'JavaScript',
point: 10,
question: 'What will we see in the console ?',
codeBoard: '...',
answers: [ '1 2 4 3 5', '1 5 4 3 2', '2 1 4 3 5', '1 5 3 4 2' ],
correctAnswer: '2 1 4 3 5',
__v: 0
},
{
_id: new ObjectId("61bc0af14da5e9ffe47fccbb"),
course: 'JavaScript',
point: 10,
question: 'What will we see in the console ?',
codeBoard: '...',
answers: [ '1 4 3 2', '1 2 4 3', '1 2 3 4', '1 4 2 3' ],
correctAnswer: '1 4 3 2',
__v: 0
}
您可以使用 $lookup
通过非常简单的管道实现此目的,如下所示:
db.users.aggregate([
{
$match: {
user_id: 1
}
},
{
"$lookup": {
"from": "quiz",
let: {
quizId: "$id",
userAnswer: "$answer"
},
pipeline: [
{
$match: {
$expr: {
$and: [
{
$eq: [
"$$quizId",
"$_id"
]
},
{
$eq: [
"$$userAnswer",
"$correctAnswer"
]
}
]
}
}
}
],
"as": "matched"
}
},
{
$group: {
_id: null,
total: {
$sum: 1
},
correct: {
$sum: {
$size: "$matched"
}
}
}
}
])
您没有给出所需的确切输入和输出,因此需要进行一些小的更改。
如果客户端发送带有所选答案的字符串中的每个问题 ID,您应该将该数组映射到:
{
id: new ObjectId("61bc09994da5e9ffe47fccb9"),
correctAnswer: "2 1 4 3 5"
}
记得定义 ObjectId 为:
const ObjectId = require('mongoose').Types.ObjectId;
然后在 $or
运算符中添加完整数组,最后将添加点的每个匹配项分组。
db.collection.aggregate({
"$match": {
$or: [
{
id: new ObjectId("61bc09994da5e9ffe47fccb9"),
correctAnswer: "2 1 4 3 5"
},
{
id: new ObjectId("61bc0af14da5e9ffe47fccbb"),
correctAnswer: "1 4 3 2"
},
. . .
]
}
},
{
"$group": {
"_id": null, // This means that every document is grouped, because there is no condition to group by
"points": {
$sum: "$point"
}
}
})
我有这个 Schema 结构
const QuizQuestionSchema = new Schema({
course: { type: String, required: true, trim: true },
point: { type: Number, required: true, trim: true, min: 1, max: 20 },
question: { type: String, required: true, trim: true },
codeBoard: { type: String, default: null, nullable: true },
answers: { type: [String], required: true, trim: true },
correctAnswer: { type: String, required: true, trim: true }
});
从客户端我得到文档的数组 ID 和选择的答案 [{id, answer}...]
。
我需要找出用户收集了多少分,比较 correctAnswer 和 answer if match add score。如何使用聚合完成此操作?
例子
客户端
[
{ id: "61bc09994da5e9ffe47fccb9", answer: "1 2 4 3 5" },
{ id: "61bc0af14da5e9ffe47fccbb", answer: "1 4 3 2" },
...
];
服务器文件
{
_id: new ObjectId("61bc09994da5e9ffe47fccb9"),
course: 'JavaScript',
point: 10,
question: 'What will we see in the console ?',
codeBoard: '...',
answers: [ '1 2 4 3 5', '1 5 4 3 2', '2 1 4 3 5', '1 5 3 4 2' ],
correctAnswer: '2 1 4 3 5',
__v: 0
},
{
_id: new ObjectId("61bc0af14da5e9ffe47fccbb"),
course: 'JavaScript',
point: 10,
question: 'What will we see in the console ?',
codeBoard: '...',
answers: [ '1 4 3 2', '1 2 4 3', '1 2 3 4', '1 4 2 3' ],
correctAnswer: '1 4 3 2',
__v: 0
}
您可以使用 $lookup
通过非常简单的管道实现此目的,如下所示:
db.users.aggregate([
{
$match: {
user_id: 1
}
},
{
"$lookup": {
"from": "quiz",
let: {
quizId: "$id",
userAnswer: "$answer"
},
pipeline: [
{
$match: {
$expr: {
$and: [
{
$eq: [
"$$quizId",
"$_id"
]
},
{
$eq: [
"$$userAnswer",
"$correctAnswer"
]
}
]
}
}
}
],
"as": "matched"
}
},
{
$group: {
_id: null,
total: {
$sum: 1
},
correct: {
$sum: {
$size: "$matched"
}
}
}
}
])
您没有给出所需的确切输入和输出,因此需要进行一些小的更改。
如果客户端发送带有所选答案的字符串中的每个问题 ID,您应该将该数组映射到:
{
id: new ObjectId("61bc09994da5e9ffe47fccb9"),
correctAnswer: "2 1 4 3 5"
}
记得定义 ObjectId 为:
const ObjectId = require('mongoose').Types.ObjectId;
然后在 $or
运算符中添加完整数组,最后将添加点的每个匹配项分组。
db.collection.aggregate({
"$match": {
$or: [
{
id: new ObjectId("61bc09994da5e9ffe47fccb9"),
correctAnswer: "2 1 4 3 5"
},
{
id: new ObjectId("61bc0af14da5e9ffe47fccbb"),
correctAnswer: "1 4 3 2"
},
. . .
]
}
},
{
"$group": {
"_id": null, // This means that every document is grouped, because there is no condition to group by
"points": {
$sum: "$point"
}
}
})