convert _id(ObjectId) to String in aggregation for lookup Spring boot

1.7k Views Asked by At

THIS IS NOT QUESTION

I had a problem for a long time to convert objectId to string in spring boot aggregation and I can't find any useful way to solve it. finally, I figure out and I like to share my way to those who have the same problem; As you know lookup need two sides of lookup the same value, for example, two sides objectId or two sides string if you have objecteId and string in another side you have to make this objectId to string and then write your lookup stage; the stage before lookup should be the project stage with usage of $toString expression like bellow:

ProjectionOperation projectionOperation = Aggregation.project(/*your nedded fields */)
.and(ConvertOperators.ToString.toString("$_id)).as("aggId");

and then you can use lookup easily like below:

Aggregation agg = Aggregation.newAggregation(
                Aggregation.match(
                        Criteria.where("cratorId").is(userId)
                )
                ,
                projectionOperation
                ,
                Aggregation.lookup("post", "aggId", "courseId", "postList"),

my full aggregation is:

ProjectionOperation projectionOperation = Aggregation.project(/*your nedded fields */)
.and(ConvertOperators.ToString.toString("$_id")).as("aggId");

Aggregation agg = Aggregation.newAggregation(
                Aggregation.match(
                        Criteria.where("creatorId").is(userId)
                )
                ,
                projectionOperation
                ,
                Aggregation.lookup("post", "aggId", "courseId", "postList")
);

return this.aggregate(agg, entityClass, Object.class).getMappedResults();

hope it can be useful

2

There are 2 best solutions below

0
On

I was looking into the answer to this question also and I found this solution.

I am using spring-data-mongodb:3.0.0.RELESE.

In your aggregation pipeline

AddFieldsOperation.builder().addField("strId")
                    .withValue(
                        ConvertOperators.ToString.toString("$_id")
                    ).build()

This is the equivalent to

{
    $addFields: {
        strId: {$toString: "$_id"}
    }
}

You can replace strId with any name you want and use it in the next operation.

1
On
List<Map> getMultiTable(){
    ProjectionOperation projectionOperation = Aggregation.project(/*your nedded fields */)
            .and(ConvertOperators.ToString.toString("$_id")).as("_id")
            .and(ConvertOperators.ToObjectId.toObjectId("$userId")).as("userId");

    Aggregation agg = Aggregation.newAggregation(
            Aggregation.match(
                    Criteria.where("status").is(0)
            ),
            projectionOperation,
            Aggregation.lookup("videoComment", "_id", "videoId", "commentList"),
            Aggregation.lookup("user", "userId", "_id", "userList")
    );

    List<Map> result = mongoTemplate.aggregate(agg, "mediaFile", Map.class).getMappedResults();
    System.out.println(result);
    return result;
}