MongoDB 国外文献查找过滤
MongoDB lookup and filter by foreign documents
我 user
collection 有角色 object 有 roleId。我还有 roles
collection 有 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();
但这不起作用。匹配过滤器 ois 使用主 table(用户)字段。但它不适用于外国 collection(roles)
有人可以帮我解决这个问题吗?
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: []
}
}
}
])
这里需要在lookup之后添加两个stage。第一个是过滤区间,第二个是消除空角色数组。
ProjectionOperation as =
project()
.and(
ArrayOperators.Filter.filter("roles")
.as("role")
.by(ComparisonOperators.Eq.valueOf("role.type").equalTo("interval")))
.as("roles");
我已经添加了项目阶段,希望您可以添加匹配阶段。以上代码未经测试,是根据工作脚本编写的。
我 user
collection 有角色 object 有 roleId。我还有 roles
collection 有 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();
但这不起作用。匹配过滤器 ois 使用主 table(用户)字段。但它不适用于外国 collection(roles)
有人可以帮我解决这个问题吗?
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: []
}
}
}
])
这里需要在lookup之后添加两个stage。第一个是过滤区间,第二个是消除空角色数组。
ProjectionOperation as =
project()
.and(
ArrayOperators.Filter.filter("roles")
.as("role")
.by(ComparisonOperators.Eq.valueOf("role.type").equalTo("interval")))
.as("roles");
我已经添加了项目阶段,希望您可以添加匹配阶段。以上代码未经测试,是根据工作脚本编写的。