Spring数据MongoDB-与其他集合的聚合

Spring数据MongoDB-与其他集合的聚合,spring,spring-data-mongodb,Spring,Spring Data Mongodb,我正在开发SpringBootV.2.1.3.RELEASE和SpringDataMongoDB。由于关键需求,我必须像下面这样建模,假设员工知道多种技术,但主要语言是任何人 因此,我决定将技术集合分开,并在员工集合中以某种方式关联员工和技术 { "_id" : ObjectId("5ec65750fdcd4e960f4b2f24"), "technologyCd" : "AB", "

我正在开发SpringBootV.2.1.3.RELEASE和SpringDataMongoDB。由于关键需求,我必须像下面这样建模,假设员工知道多种技术,但主要语言是任何人

因此,我决定将技术集合分开,并在员工集合中以某种方式关联员工和技术

{
    "_id" : ObjectId("5ec65750fdcd4e960f4b2f24"),
    "technologyCd" : "AB",
    "technologyName" : "My ABC",
    "ltechnologyNativeName" : "XY",
    "status" : "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);
所以,我做了如下的联想-

注:一名员工可以使用多种技术

一名员工可以与多种技术相关联

员工只能拥有一项基本技术

我使用了下面的查询,如何查询技术文档以获得结果并映射它并创建最终对象

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);

如果您在代码中使用下面的查找操作,您应该能够按照预期得到答案,并且不需要在代码中使用组操作

编辑回答:这就是整个代码的样子。还有一件事,您不需要投影,如果需要,请尝试仅投影特定字段,并且作为查找操作的一部分,不要使用与集合中相同的字段,否则它将覆盖employee集合中的现有数据

{
    "_id" : ObjectId("5ec65750fdcd4e960f4b2f24"),
    "technologyCd" : "AB",
    "technologyName" : "My ABC",
    "ltechnologyNativeName" : "XY",
    "status" : "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);
标准=新标准();
条件.与运算符(
StringUtils.isNotBlank(firstName)?条件。其中(“firstName”).is(firstName.toUpperCase())
:标准。其中(“”),
StringUtils.isNotBlank(lastName)?条件。其中(“lastName”).is(lastName.toUpperCase())
:标准。其中(“”),
StringUtils.isNotBlank(email)?条件。其中(“email”)是(email.toUpperCase())
:标准。其中(“”),
StringUtils.isNotBlank(technologyCd)?标准。其中(“employeeTechnologyRefs.technologyCd”)是(technologyCd.toUpperCase())
:标准。其中(“”);
MatchOperation matchStage=聚合。匹配(标准);
/*GroupOperation-groupOp=聚合
.group(“名字”、“姓氏”、“电子邮件”、“身份证”)
.addToSet(“员工技术参考”)。作为(“员工技术参考”);
*/
LookupOperation LookupOperation=LookupOperation.newLookup()。
来自(“技术、集合、名称”)。
localField(“employeeTechnologyRefs.technologyCd”)。
外域(“technologyCd”)。
as(“员工技术名称”);
/*ProjectionOperationProjectStage=Aggregation.project(“employeeTechnologyRefs”);
*/  
//如果您想从employee数组中投影特定字段,您可以使用以下命令。
ProjectionOperationProjectStage=Aggregation.project(“employeeTechnologyRefs.fieldName”)
聚合聚合=聚合.newAggregation(matchStage、lookupOperation、projectStage);
AggregationResults=mongoTemplate.aggregate(聚合,mongoTemplate.getCollectionName(Employee.class),CustomObject.class);
系统输出打印项次(结果);

您希望最终结果是什么样的?如果你想加入结果,你可以使用$lookup stage匹配other collection@DeepakSingh中的数据-我已经更新了结果,你能帮我修改查询吗?员工和技术集合是如何链接的?在哪一处?你能分享一下吗?我想你可以在这里使用查找阶段。它们应该链接到“technologyCd”上,因为在技术收藏中,它是一个独特的领域,将尝试。。。它是否返回technologyCd匹配的所有操作?此时此刻,我正在努力映射
CustomObject
,您能否演示如何将其与下面所示的聚合一起使用?您能否分享准确的数据(即,您的员工集合和技术集合是什么样子的)。嘿,我已经在上面分享过了,第一个json文档是技术文档,另一个json文档是员工文档。您还需要什么?更新了答案,应该是这样的,请检查您的CustomObject是否与结果结构匹配。