如何使用Panache和MongoDB投影聚合查询结果?

huangapple go评论61阅读模式
英文:

How to project the result of an aggregate query result with Panache and MongoDB?

问题

如何将结果投影到自定义类?项目()只存在于find()中。

英文:

Consider this method:

public static Uni<List<ReactivePanacheMongoEntityBase>> getAverage(String productId) {
    List<Bson> pipeline = new ArrayList<>();
    Bson match = Aggregates.match(Filters.eq("productId", new ObjectId(productId)));
    Bson group = Aggregates.group("$productId", new BsonField("Average", new Document("$avg", "$score")));
    pipeline.add(match);
    pipeline.add(group);
    return Rating.mongoCollection().aggregate(pipeline).collect().asList();
}

How to I project the results to a custom class? The project() only exists in conjunction with find() 🤔

答案1

得分: 1

在MongoDB中,您可以使用project聚合阶段来指定聚合管道返回的文档的形状。要将结果映射到自定义的Java类,您可以结合使用project阶段和编解码器注册表。

让我们创建一个自定义类来表示结果。假设您希望将结果映射到名为AverageRating的类中。

public class AverageRating {
    private ObjectId productId;
    private Double average;

    // Getters and setters
}

修改getAverage方法以包含project阶段,并将结果映射到AverageRating类。您可以使用Uni类的map方法来实现这一点。

import org.bson.Document;
import org.bson.codecs.configuration.CodecRegistries;
import org.bson.codecs.configuration.CodecRegistry;
import org.bson.codecs.pojo.PojoCodecProvider;
import io.smallrye.mutiny.Uni;

import java.util.ArrayList;
import java.util.List;

import static com.mongodb.client.model.Projections.fields;
import static com.mongodb.client.model.Projections.computed;

public static Uni<List<AverageRating>> getAverage(String productId) {
    List<Bson> pipeline = new ArrayList<>();
    Bson match = Aggregates.match(Filters.eq("productId", new ObjectId(productId)));
    Bson group = Aggregates.group("$productId", new BsonField("average", new Document("$avg", "$score")));
    Bson project = Aggregates.project(fields(computed("productId", "$_id"), computed("average", "$average")));
    pipeline.add(match);
    pipeline.add(group);
    pipeline.add(project);

    CodecRegistry pojoCodecRegistry = CodecRegistries.fromRegistries(
            MongoClientSettings.getDefaultCodecRegistry(),
            CodecRegistries.fromProviders(PojoCodecProvider.builder().automatic(true).build())
    );

    return Rating.mongoCollection()
                 .withCodecRegistry(pojoCodecRegistry)
                 .aggregate(pipeline, AverageRating.class)
                 .collect()
                 .asList();
}

在上面的示例中,project阶段指定了聚合管道返回的文档的形状。它还使用编解码器注册表将结果映射到AverageRating POJO(普通的Java对象)。请注意,aggregate方法现在使用AverageRating.class进行参数化,指示结果应映射到的类的类型。

英文:

In MongoDB, you can use the project aggregation stage to specify the shape of the documents returned by the aggregation pipeline. To map the result to a custom Java class, you can use a combination of the project stage and the codec registry.

Let's create a custom class to represent the result. Suppose you want to map the result to a class called AverageRating.

public class AverageRating {
    private ObjectId productId;
    private Double average;

    // Getters and setters
}

Modify the getAverage method to include the project stage and to map the results to AverageRating class. You can use the map method of the Uni class for this.

import org.bson.Document;
import org.bson.codecs.configuration.CodecRegistries;
import org.bson.codecs.configuration.CodecRegistry;
import org.bson.codecs.pojo.PojoCodecProvider;
import io.smallrye.mutiny.Uni;

import java.util.ArrayList;
import java.util.List;

import static com.mongodb.client.model.Projections.fields;
import static com.mongodb.client.model.Projections.computed;

public static Uni&lt;List&lt;AverageRating&gt;&gt; getAverage(String productId) {
    List&lt;Bson&gt; pipeline = new ArrayList&lt;&gt;();
    Bson match = Aggregates.match(Filters.eq(&quot;productId&quot;, new ObjectId(productId)));
    Bson group = Aggregates.group(&quot;$productId&quot;, new BsonField(&quot;average&quot;, new Document(&quot;$avg&quot;, &quot;$score&quot;)));
    Bson project = Aggregates.project(fields(computed(&quot;productId&quot;, &quot;$_id&quot;), computed(&quot;average&quot;, &quot;$average&quot;)));
    pipeline.add(match);
    pipeline.add(group);
    pipeline.add(project);

    CodecRegistry pojoCodecRegistry = CodecRegistries.fromRegistries(
            MongoClientSettings.getDefaultCodecRegistry(),
            CodecRegistries.fromProviders(PojoCodecProvider.builder().automatic(true).build())
    );

    return Rating.mongoCollection()
                 .withCodecRegistry(pojoCodecRegistry)
                 .aggregate(pipeline, AverageRating.class)
                 .collect()
                 .asList();
}

In the above example, the project stage specifies the shape of the documents returned by the aggregation pipeline. It is also using the codec registry to map the result to the AverageRating POJO (Plain Old Java Object). Note that the aggregate method is now parameterized with AverageRating.class which indicates the type of class the results should be mapped to.

huangapple
  • 本文由 发表于 2023年6月26日 20:32:47
  • 转载请务必保留本文链接:https://go.coder-hub.com/76556718.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定