[toc]
问题描述
现在我有一个这样的 mongodb 文档模型 Article
author、group
这两个字段分别左外部联接 User
和ArticleGroup
两个集合
我使用的是 mongoose 对象文档模型(ODM)库,集合名称都是大写的
const ArticleSchema = new mongoose.Schema({
title: { type: String, required: true },
author: { type: mongoose.Schema.Types.ObjectId, ref: "User", required: true },
group: { type: mongoose.Schema.Types.ObjectId, ref: "ArticleGroup" },
});
// ArticleGroup
const ArticleGroupSchema = new mongoose.Schema({
name: { type: String, required: true },
desc: { type: String, default: "" },
state: { type: String, required: true, default: "public" },
members: [
{
desc: String,
role: String,
user: { type: mongoose.Schema.Types.ObjectId, ref: "User", required: true },
},
],
});
// User
const userSchema = new mongoose.Schema(
{
email: { type: String, unique: true },
password: String,
},
);
test data :
{
_id: "6131aa5b367318e2df14b988",
title: "功能更新清单",
author: ObjectId("607edeb4b1e1bea9acb5af38"),
group: ObjectId("612d00a43c52975d4ade10d4")
}
我预期的结果
我想在 aggregate 聚合操作内通过比较 author._id == group.members.user 的值,向文档添加一个新字段 can_edit。
Article.aggregate([
{
$lookup: {
from: "users",
localField: "author",
foreignField: "_id",
as: "author",
},
},
{
$lookup: {
from: "articlegroups",
localField: "group",
foreignField: "_id",
as: "group"
}
},
{
$addFields: {
can_edit: {
$eq: ["$group.members.user", "$author._id"],
},
}
}
])
可是我得到的 can_edit 值始终是 false,我确定在我的测试数据中 author._id 的值和group.members.user 是相同。
期望返回的文档结构:
{
_id: "6131aa5b367318e2df14b988",
can_edit: true,
title: "功能更新清单",
author: {
_id: "607edeb4b1e1bea9acb5af38",
email: "frmachao@126.com",
},
group: {
_id: "612d00a43c52975d4ade10d4",
desc: "开发",
state: "public",
name: "开发小组",
members: [
{
_id: "612d00a43c52975d4ade10d5",
role: "admin",
user: "607edeb4b1e1bea9acb5af38",
}
]
}
}
刚刚,我找到一个相似的问题 stackoverflow。上面提到: in (聚合)来验证数组中的值
于是我尝试做了下面更改
Article.aggregate([
{
$lookup: {
from: "users",
localField: "author",
foreignField: "_id",
as: "author",
},
},
{
$lookup: {
from: "articlegroups",
localField: "group",
foreignField: "_id",
as: "group"
}
},
{
$addFields: {
can_edit: {
$in: [
"$author._id",
"$group.members.user"
],
},
},
}
])
但是遇到了新问题: $in requires an array as a second argument
在挣扎了100分钟: 尝试用搜索引擎检索我遇到的问题、去翻阅$eq聚合阶段
的文档、咨询微信里做过服务端开发的网友
可是问题还是没有解决,最后我决定去社区提问。
去社区提问
- 国内 segmentfault
- 国外的 stackoverflow
mongoplayground
stackoverflow 上面,一位热心的马来西亚程序员帮我解决了问题:
他告诉我 应该 group.members must be array checking
,也就是先要判断group.members 是不是一个数组。
分析:在我定义的数据模型里,group 并不是一个必填项,所以 group 字段可能为空
const ArticleSchema = new mongoose.Schema({
title: { type: String, required: true },
author: { type: mongoose.Schema.Types.ObjectId, ref: "User", required: true },
group: { type: mongoose.Schema.Types.ObjectId, ref: "ArticleGroup" },
});
热情的马来西亚程序员 甚至给出了完整的 判断 group.members must be array 的样例,附上调试地址,respect!!
db.collection.aggregate([
{
$addFields: {
can_edit: {
$switch: {
branches: [
{
case: {
$ne: [
{
"$type": "$group.members"
},
"array"
]
},
then: false
},
{
case: {
$ne: [
{
"$type": "$group.members"
},
"array"
]
},
then: false
},
{
case: {
$in: [
"$author._id",
"$group.members.user"
]
},
then: true
}
],
default: false
}
}
}
}
])
收获
- mongoplayground一个网站 可以在线调试 mongoDB的查询
- in (聚合)来验证数组中的值。
- 去社区提问需要注意:描述清楚自己的问题,不要带上自己的业务细节把问题剥离出来,最好能提供一个在线运行的
playground
。
🤔思考
- 自学能力差: 为什么我翻看文档时没有看到
$eq (聚合)比较不同于查询 eq opeator 的值和类型,后者可以比较任何类型的值。需要 $in (聚合)来验证数组中的值
- 英语很差:stackoverflow 上编写的提问描述全部来自 google 翻译 中--》英