mongodb - MongoDB 按外部文档查找和过滤
问题描述
我user
收集了具有角色对象的集合,该对象具有角色 ID。我也有roles
具有 id 的集合。现在,对于每个角色,我想获取用户列表。
前任:
[
{
"name": "Scott",
"isActive": true,
"role": {
"roleId": "123432"
}
},
{
"name": "John",
"isActive": true,
"role": {
"roleId": "123432"
}
},
{
"name": "Scott",
"isActive": true,
"role": {
"roleId": "556432"
}
}
]
角色数据:
[
{
"id": "123432"
"name": "admin",
"type": "internal"
},
{
"id": "556432"
"name": "owner",
"type": "external"
},
{
"id": "556432"
"name": "owner",
"type": "internal"
}
]
现在我想获取所有类型的角色internal
及其相关用户:
所以,输出应该是,
[
{
"role": "123432",
"users": [
{
"name": "Scott",
"role": {
"roleId": "123432"
}
},
{
"name": "John",
"role": {
"roleId": "123432"
}
}
],
{
"role": "556432",
"users": []
}
}
]
这是我在 SpringBoort 中的聚合:
LookupOperation lookupOperation = LookupOperation.newLookup().from("roles").localField("roleId")
.foreignField("_id").as("roles");
AggregationOperation match = Aggregation.match(Criteria.where("type").is("internal"));
Aggregation aggregation = Aggregation.newAggregation(lookupOperation, match);
List<UserDTO> results = mongoTemplate.aggregate(aggregation, "users", UserDTO.class).getMappedResults();
但这不起作用。匹配过滤器与主表(用户)字段一起使用。但它不适用于外国收藏(角色)
有人可以帮我吗?
解决方案
AggregationOperation isActiveMatch= Aggregation.match(Criteria.where("isActive").is(true));
应该是第一场比赛。
LookupOperation lookupOperation = LookupOperation.newLookup().from("roles").localField("roleId")
.foreignField("_id").as("roles");
AggregationOperation match = Aggregation.match(Criteria.where("type").is("internal"));
Aggregation aggregation = Aggregation.newAggregation(isActiveMatch,lookupOperation, match);
更新 1
你可能会期待这样,
db.user.aggregate([
{
"$lookup": {
"from": "roles",
"localField": "role.roleId",
"foreignField": "id",
"as": "roles"
}
},
{
$project: {
roles: {
"$filter": {
"input": "$roles",
"cond": {
$eq: [
"$$this.type",
"internal"
]
}
}
}
}
},
{
$match: {
roles: {
$ne: []
}
}
}
])
工作Mongo游乐场
这里需要在lookup之后添加两个stage。第一个是过滤区间,第二个是消除空角色数组。
ProjectionOperation as =
project()
.and(
ArrayOperators.Filter.filter("roles")
.as("role")
.by(ComparisonOperators.Eq.valueOf("role.type").equalTo("interval")))
.as("roles");
我已经添加了项目阶段,希望您可以添加匹配阶段。上面的代码未经测试,而是基于工作脚本编写的。
推荐阅读
- sql - SQL 如何找到最流行的?
- reactjs - 分配一个取决于多个 Promise 完成情况的值
- istio - Istio 1.4.7 - Kiali pod 无法启动
- javascript - Gatsby - 尝试使用 URL 呈现图像 - 无法读取未定义的属性“0”
- azure - 构建代理不断失败并出现错误 ERR:证书链中的自签名证书
- c++ - 用于访问结构数据成员的 AST 节点
- java - JavaFX MVC 包间通信
- amazon-web-services - 在 Lambda 上运行 Prometheus
- javascript - Vue 在使用 v-for 时无法读取 null 的属性
- firebase - Firestore 规则:执行 setData 时出错,PERMISSION_DENIED