MongoTemplate Aggregation for nested objects and multiple unwinds

35 Views Asked by At

I am using for a Mongotemplate with spring boot to implement a whatsapp like stories implementation. My story model is as follows:

    private String id;
    private String userId;
    private String mediaType;
    private String url;
    private Double duration;
    private String caption;
    private Long expiresAt;
    private String color;
    private Long createdOn;
    private Set<String> viewedByUsers = new HashSet<>();

I wish to return stories grouped by userId with userDetails as in the below result. This is working fine. But additionally I also wish to convert the viewedByUsers set of userIds to a set of user objects similar to the one in userDetails. ViewedByUsers can have empty or null array in the db. This is the current response:

{
    "body": [
        
        {
            "userDetails": {
                "id": "1685767061466202615",
                "name": "Arvind",
                "avatar": "https://d371tz2ffol68z.cloudfront.net/bhakti_images/1692095460651_1692095460651-IMG_20230815_155953.jpg"
            },
            "stories": [
                {
                    "id": "344584545173569",
                    "createdOn": 1698395815385,
                    "modifiedOn": 1698395815385,
                    "userId": "1685767061466202615",
                    "mediaType": "video",
                    "url": "https://raw.githubusercontent.com/blackmann/storyexample/master/assets/small.mp4",
                    "duration": 4.0,
                    "caption": "robo robo. robo me.",
                    "expiresAt": 1698733575000,
                    "color": "",
                    "viewedByUsers": [
                        "1691991110647605477"
                    ]
                }
            ]
        }
    ]
}

My current Aggregation query is:

AggregationOperation matchStage = Aggregation.match(
                new Criteria().andOperator(
                        Criteria.where("userId").in(users),
                        Criteria.where("expiresAt").gt(currentMillis),
                        Criteria.where("appId").is(app)
                )
        );

Aggregation aggregation = Aggregation.newAggregation(
            matchStage,
            Aggregation.lookup("user", "userId", "_id", "userDetails"),
            Aggregation.unwind("userDetails", true),
            Aggregation.group("userId")
                .first("userDetails").as("userDetails")
                .push("$$ROOT").as("stories"),
            Aggregation.project()
                    .and("userDetails._id").as("userDetails.id")
                    .and("userDetails.name").as("userDetails.name")
                    .and("userDetails.avatar").as("userDetails.avatar")// Assuming there's only one user document per userId
                    .and("stories").as("stories")
        );

The desired response is as:

    "body": [
        {
            "userDetails": {
                "id": "1685767061466202615",
                "name": "Arvind",
                "avatar": "https://d371tz2ffol68z.cloudfront.net/bhakti_images/1692095460651_1692095460651-IMG_20230815_155953.jpg"
            },
            "stories": [
                {
                    "id": "344584545173569",
                    "createdOn": 1698395815385,
                    "modifiedOn": 1698395815385,
                    "userId": "1685767061466202615",
                    "mediaType": "video",
                    "url": "https://raw.githubusercontent.com/blackmann/storyexample/master/assets/small.mp4",
                    "duration": 4.0,
                    "caption": "robo robo. robo me.",
                    "expiresAt": 1698733575000,
                    "color": "",
                    "viewedByUsers": [
                        {
                          "id": "1691991110647605477",
                          "name": "Deep",
                          "avatar": "https://d371tz2ffol68z.cloudfront.net/user/deep.png"
                        }
                    ]
                }
            ]
        }
    ]
}```


Is it possible to further club the stories as viewed and notviewed in the same query provided the userId is in viewedByUsers array?
0

There are 0 best solutions below