Spring 数据 MongoDB - 与其他集合的聚合
Spring Data MongoDB - Aggregation with other collection as well
我正在研究 Spring Boot v.2.1.3.RELEASE 和 Spring Data MongoDB。由于关键要求,我必须像下面这样建模,假设员工知道多种技术,但主要语言是任何人。
因此,我决定将技术集合分开,并在员工集合中以某种方式关联员工和技术。
{
"_id" : ObjectId("5ec65750fdcd4e960f4b2f24"),
"technologyCd" : "AB",
"technologyName" : "My ABC",
"ltechnologyNativeName" : "XY",
"status" : "A"
}
所以,我完成了如下关联 -
Note: Multiple Technologies can be associated with one Employee
One Employee can be associated with multiple technologies
Employee can have one and only one Primary Technology
{
"_id" : ObjectId("5ec507c72d8c2136245d35ce"),
"firstName" : "John",
"lastName" : "Doe",
"email" : "j.d@gmail.com",
.......
.......
.......
"employeeTechnologyRefs" : [
{
"technologyCd" : "AB",
"primaryTechnologySw" : "Y",
"Active" : "A"
},
{
"technologyCd" : "AB",
"primaryTechnologySw" : "N",
"Active" : "A"
},
{
"technologyCd" : "PR",
"primaryTechnologySw" : "N",
"Active" : "A"
},
{
"technologyCd" : "PR",
"primaryTechnologySw" : "N",
"Active" : "A"
}
],
"countryPhoneCodes" : [
"+352"
],
....
...
}
我使用了以下查询,如何查询技术文档以获得结果并将其映射并创建最终对象?
Criteria criteria = new Criteria();
criteria.andOperator(
StringUtils.isNotBlank(firstName) ? Criteria.where("firstName").is(firstName.toUpperCase())
: Criteria.where(""),
StringUtils.isNotBlank(lastName) ? Criteria.where("lastName").is(lastName.toUpperCase())
: Criteria.where(""),
StringUtils.isNotBlank(email) ? Criteria.where("email").is(email.toUpperCase())
: Criteria.where(""),
StringUtils.isNotBlank(technologyCd) ? Criteria.where("employeeTechnologyRefs.technologyCd").is(technologyCd.toUpperCase())
: Criteria.where(""));
MatchOperation matchStage = Aggregation.match(criteria);
GroupOperation groupOp = Aggregation
.group("firstName", "lastName", "email","_id")
.addToSet("employeeTechnologyRefs").as("employeeTechnologyRefs");
ProjectionOperation projectStage = Aggregation.project("employeeTechnologyRefs");
Aggregation aggregation = Aggregation.newAggregation(matchStage, groupOp, projectStage);
AggregationResults<CustomObject> results = mongoTemplate.aggregate(aggregation, mongoTemplate.getCollectionName(Employee.class), CustomObject.class);
System.out.println(results);
结果应如下所示
{
"_id" : ObjectId("5ec507c72d8c2136245d35ce"),
"firstName" : 442,
"lastName" : "LU",
"email" : "LUX",
.......
.......
.......
"employeeTechnologyRefs" : [
{
"technologyCd" : "AB",
"technologyName" : "My ABC",
"ltechnologyNativeName" : "XY",
"primaryTechnologySw" : "Y",
"Active" : "A"
},
{
"technologyCd" : "AB",
"technologyCd" : "AB",
"technologyName" : "My ABC",
"ltechnologyNativeName" : "XY",
"primaryTechnologySw" : "Y",
"Active" : "A"
},
{
"technologyCd" : "PR",
"technologyCd" : "AB",
"technologyName" : "My ABC",
"ltechnologyNativeName" : "XY",
"primaryTechnologySw" : "Y",
"Active" : "A"
},
{
"technologyCd" : "PR",
"technologyCd" : "AB",
"technologyName" : "My ABC",
"ltechnologyNativeName" : "XY",
"primaryTechnologySw" : "Y",
"Active" : "A"
}
],
....
}
如果您在代码中使用以下查找操作,您应该可以得到预期的答案,并且您的代码中不需要组操作。
编辑后的答案:这就是整个代码的样子。还有一件事,您不需要投影,如果您只需要尝试投影特定字段,并且作为查找操作的一部分,请不要使用与集合中相同的字段,否则它将覆盖员工集合中的现有数据。
Criteria criteria = new Criteria();
criteria.andOperator(
StringUtils.isNotBlank(firstName) ? Criteria.where("firstName").is(firstName.toUpperCase())
: Criteria.where(""),
StringUtils.isNotBlank(lastName) ? Criteria.where("lastName").is(lastName.toUpperCase())
: Criteria.where(""),
StringUtils.isNotBlank(email) ? Criteria.where("email").is(email.toUpperCase())
: Criteria.where(""),
StringUtils.isNotBlank(technologyCd) ? Criteria.where("employeeTechnologyRefs.technologyCd").is(technologyCd.toUpperCase())
: Criteria.where(""));
MatchOperation matchStage = Aggregation.match(criteria);
/*GroupOperation groupOp = Aggregation
.group("firstName", "lastName", "email","_id")
.addToSet("employeeTechnologyRefs").as("employeeTechnologyRefs");
*/
LookupOperation lookupOperation = LookupOperation.newLookup().
from("technology_collection_name").
localField("employeeTechnologyRefs.technologyCd").
foreignField("technologyCd").
as("employeeTechnologyRefsOtherName");
/* ProjectionOperation projectStage = Aggregation.project("employeeTechnologyRefs");
*/
// And if you want to project specific field from employee array you can use something like.
ProjectionOperation projectStage = Aggregation.project("employeeTechnologyRefs.fieldName")
Aggregation aggregation = Aggregation.newAggregation(matchStage, lookupOperation, projectStage);
AggregationResults<CustomObject> results = mongoTemplate.aggregate(aggregation, mongoTemplate.getCollectionName(Employee.class), CustomObject.class);
System.out.println(results);
我正在研究 Spring Boot v.2.1.3.RELEASE 和 Spring Data MongoDB。由于关键要求,我必须像下面这样建模,假设员工知道多种技术,但主要语言是任何人。
因此,我决定将技术集合分开,并在员工集合中以某种方式关联员工和技术。
{
"_id" : ObjectId("5ec65750fdcd4e960f4b2f24"),
"technologyCd" : "AB",
"technologyName" : "My ABC",
"ltechnologyNativeName" : "XY",
"status" : "A"
}
所以,我完成了如下关联 -
Note: Multiple Technologies can be associated with one Employee
One Employee can be associated with multiple technologies
Employee can have one and only one Primary Technology
{
"_id" : ObjectId("5ec507c72d8c2136245d35ce"),
"firstName" : "John",
"lastName" : "Doe",
"email" : "j.d@gmail.com",
.......
.......
.......
"employeeTechnologyRefs" : [
{
"technologyCd" : "AB",
"primaryTechnologySw" : "Y",
"Active" : "A"
},
{
"technologyCd" : "AB",
"primaryTechnologySw" : "N",
"Active" : "A"
},
{
"technologyCd" : "PR",
"primaryTechnologySw" : "N",
"Active" : "A"
},
{
"technologyCd" : "PR",
"primaryTechnologySw" : "N",
"Active" : "A"
}
],
"countryPhoneCodes" : [
"+352"
],
....
...
}
我使用了以下查询,如何查询技术文档以获得结果并将其映射并创建最终对象?
Criteria criteria = new Criteria();
criteria.andOperator(
StringUtils.isNotBlank(firstName) ? Criteria.where("firstName").is(firstName.toUpperCase())
: Criteria.where(""),
StringUtils.isNotBlank(lastName) ? Criteria.where("lastName").is(lastName.toUpperCase())
: Criteria.where(""),
StringUtils.isNotBlank(email) ? Criteria.where("email").is(email.toUpperCase())
: Criteria.where(""),
StringUtils.isNotBlank(technologyCd) ? Criteria.where("employeeTechnologyRefs.technologyCd").is(technologyCd.toUpperCase())
: Criteria.where(""));
MatchOperation matchStage = Aggregation.match(criteria);
GroupOperation groupOp = Aggregation
.group("firstName", "lastName", "email","_id")
.addToSet("employeeTechnologyRefs").as("employeeTechnologyRefs");
ProjectionOperation projectStage = Aggregation.project("employeeTechnologyRefs");
Aggregation aggregation = Aggregation.newAggregation(matchStage, groupOp, projectStage);
AggregationResults<CustomObject> results = mongoTemplate.aggregate(aggregation, mongoTemplate.getCollectionName(Employee.class), CustomObject.class);
System.out.println(results);
结果应如下所示
{
"_id" : ObjectId("5ec507c72d8c2136245d35ce"),
"firstName" : 442,
"lastName" : "LU",
"email" : "LUX",
.......
.......
.......
"employeeTechnologyRefs" : [
{
"technologyCd" : "AB",
"technologyName" : "My ABC",
"ltechnologyNativeName" : "XY",
"primaryTechnologySw" : "Y",
"Active" : "A"
},
{
"technologyCd" : "AB",
"technologyCd" : "AB",
"technologyName" : "My ABC",
"ltechnologyNativeName" : "XY",
"primaryTechnologySw" : "Y",
"Active" : "A"
},
{
"technologyCd" : "PR",
"technologyCd" : "AB",
"technologyName" : "My ABC",
"ltechnologyNativeName" : "XY",
"primaryTechnologySw" : "Y",
"Active" : "A"
},
{
"technologyCd" : "PR",
"technologyCd" : "AB",
"technologyName" : "My ABC",
"ltechnologyNativeName" : "XY",
"primaryTechnologySw" : "Y",
"Active" : "A"
}
],
....
}
如果您在代码中使用以下查找操作,您应该可以得到预期的答案,并且您的代码中不需要组操作。
编辑后的答案:这就是整个代码的样子。还有一件事,您不需要投影,如果您只需要尝试投影特定字段,并且作为查找操作的一部分,请不要使用与集合中相同的字段,否则它将覆盖员工集合中的现有数据。
Criteria criteria = new Criteria();
criteria.andOperator(
StringUtils.isNotBlank(firstName) ? Criteria.where("firstName").is(firstName.toUpperCase())
: Criteria.where(""),
StringUtils.isNotBlank(lastName) ? Criteria.where("lastName").is(lastName.toUpperCase())
: Criteria.where(""),
StringUtils.isNotBlank(email) ? Criteria.where("email").is(email.toUpperCase())
: Criteria.where(""),
StringUtils.isNotBlank(technologyCd) ? Criteria.where("employeeTechnologyRefs.technologyCd").is(technologyCd.toUpperCase())
: Criteria.where(""));
MatchOperation matchStage = Aggregation.match(criteria);
/*GroupOperation groupOp = Aggregation
.group("firstName", "lastName", "email","_id")
.addToSet("employeeTechnologyRefs").as("employeeTechnologyRefs");
*/
LookupOperation lookupOperation = LookupOperation.newLookup().
from("technology_collection_name").
localField("employeeTechnologyRefs.technologyCd").
foreignField("technologyCd").
as("employeeTechnologyRefsOtherName");
/* ProjectionOperation projectStage = Aggregation.project("employeeTechnologyRefs");
*/
// And if you want to project specific field from employee array you can use something like.
ProjectionOperation projectStage = Aggregation.project("employeeTechnologyRefs.fieldName")
Aggregation aggregation = Aggregation.newAggregation(matchStage, lookupOperation, projectStage);
AggregationResults<CustomObject> results = mongoTemplate.aggregate(aggregation, mongoTemplate.getCollectionName(Employee.class), CustomObject.class);
System.out.println(results);