【问题标题】:lookup doesn't work properly when used with getMappedResults()与 getMappedResults() 一起使用时查找无法正常工作
【发布时间】:2021-01-16 22:30:25
【问题描述】:

我有以下代码,getRawResult 和 getMappedResult 的答案不同。我想知道如何在 mappedResults 中包含 user 和 place 对象。

     // This methd searches the given string in reviews of the given country
                    
        MatchOperation matchRegion = Aggregation.match(Criteria.where("Country").is("Germany"));
                    
        //To match the review
        TextCriteria criteria = TextCriteria.forDefaultLanguage().matchingAny(text);
        MatchOperation match = Aggregation.match(criteria);         

        GroupOperation group = Aggregation.group("place.place_name").push("$$ROOT").as("reviews").sum("textScore")
                .as("score");

        ProjectionOperation project = Aggregation
                .project("some_point", "place", "user", "date")
                .andExpression("{$meta: \"textScore\"}").as("textScore");               
    
        SortOperation sortByScore = Aggregation.sort(Sort.Direction.DESC, "score");

        Aggregation aggregation = Aggregation.newAggregation(match,Aggregation.lookup("place","placeId","_id","place"),
                Aggregation.unwind("place"),Aggregation.lookup("user","userId","_id","user"),
                Aggregation.unwind("user") , matchRegion, project, group, sortByScore);

        
        AggregationResults<ReviewAggrResults> results = mongoTemplate.aggregate(aggregation,
                mongoTemplate.getCollectionName(Review.class), ReviewAggrResults.class);    
        
        List<ReviewAggrResults> result = results.getMappedResults();
            
        Object object = mongoTemplate.aggregate(aggregation, Review.class, Object.class).getRawResults();


        Print.print("result object rawResults", object); 
        Print.print("result reviewaggrresult: ", result);
        

使用上面的代码,getRawResults 和 ReviewAggrResult 的打印结果如下:

原始结果:

  {
      "results" : [ {
        "_id" : "ibis Heidelberg, Willy-Brandt-Platz 3, 69115 Heidelberg, Germany",
        "reviews" : [ {
          "_id" : {
            "timestamp" : 1610817567,
            "date" : 1610817567000
          },
          "some_point" : "something",         
          "date" : "Sat Jan 16 18:19:27 CET 2021",
          "place" : {
            "_id" : {
              "timestamp" : 1610817567,
              "date" : 1610817567000
            },
            "place_name" : "ibis Heidelberg, Willy-Brandt-Platz 3, 69115 Heidelberg, Germany",
            "country" : "Germany",
          },
          "user" : {
            "_id" : {
              "timestamp" : 1610817549,
              "date" : 1610817549000
            },
            "firstname" : "test1first",
            "lastname" : "test1last",
          },
          "textScore" : 5.25
        } ],
        "score" : 5.25
      } ],
      "ok" : 1.0
    }

映射结果:

[ {
  "reviews" : [ {
    "id" : "6003201f98afbc730e4f58eb",
    "some_point" : "something",
    "placeId" : null,
    "userId" : null,
    "date" : "Sat Jan 16 18:19:27 CET 2021",
    "textScore" : 5.25
  } ],
  "id" : "ibis Heidelberg, Willy-Brandt-Platz 3, 69115 Heidelberg, Germany",
  "userId" : null,
  "user" : null,
  "score" : 5.25
} ]

为什么它们不同?原始结果是正确的,但是当它被映射时,地点和用户对象被删除。我怎样才能将它们也包含在 mappedResult 中?

【问题讨论】:

    标签: java spring mongodb aggregation-framework mongotemplate


    【解决方案1】:

    getMappedResults() 为您提供映射类和聚合结果的直接映射。看看这里有什么问题。当你拿getRawResult()为例,我只会拿place

    "place" : {
        "_id" : {
          "timestamp" : 1610817567,
          "date" : 1610817567000
        },
        "place_name" : "ibis Heidelberg, Willy-Brandt-Platz 3, 69115 Heidelberg, Germany",
        "country" : "Germany",
    }
    

    place 是一个对象,它有_id、place_name 和country。但是在您的映射类Review 中,您只有placeId,结果没有提供。所以它不能做点对点的映射。你能做的是

    class Place{
        ObjectId _id;
        String place_name;
        String country;
        //Constrtuctors, Getters, Setters
    }
    

    在你的复习课上,

    class Review{
        // other fields
        Place place;
    }
    

    您也需要对其他对象或数组执行相同的操作。这应该工作

    【讨论】:

    • 非常感谢您的回答,但我的目标正是减少冗余并避免将整个 Place 对象保存在 Review 中。如果我将place 放在Review 中,我根本不需要在聚合中展开和查找,并且代码可以工作。我想避免只在 Review 类和搜索中使用 placeid,使用 id 提取 place 对象。
    • 在这种情况下,你可以做的是,你不需要有一个输出类,在BasicDbObject.class 中获取它,比如mongoTemplate.aggregate(aggregation, mongoTemplate.getCollectionName(Review.class), BasicDbObject.class)。如果需要,您可以转换为 Document。(在我的情况下,出于几个原因,我在我的项目中转换为 Document)。然后你可以使用get()获取特定字段并将其分配给ReviewAggrResults的字段,
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-01-23
    • 1970-01-01
    • 2017-12-14
    • 2020-08-19
    • 2013-02-06
    • 2019-02-02
    • 2021-10-15
    相关资源
    最近更新 更多