Search code examples
javaspringmongodbnosqlprojection

Mongo DB Bson and Java: adding and returning field in child documents that is only present in the parent?


I have the following document structure in my cosmos DB (using mongo query language):

Child:

    {
    id: doc_123_2
    parent_id: 123
    active: true
}

Parent:

{
_id: doc_123
parent_id: 123
active: true
parent_desc: sample parent desc
}   

In my code below I am trying to return the "parent_desc" field in all the child docs relating to it - however I am not able to get it to populate in the child docs, what am I doing wrong?

I can manually hard code this field in my projection method but that is not what I want - I want it pulled from parent doc.

I think that my addFieldsStage in the code below does not seem to be doing anything?

private List<Bson> createQuery() {

    List<Bson> pipeline = new ArrayList<>();

    Bson lookupStage = Aggregates.lookup(
            "myCollection",
            "parent_id",
            "parent_id",
            "children"
    );
    pipeline.add(lookupStage);

    // adding parent_desc from parent docs into children?
    Bson addFieldsStage = Aggregates.addFields(
            new Field<>("parent_desc", "$ROOT.parent_desc")
    );
    pipeline.add(addFieldsStage);

    pipeline.add(Aggregates.unwind("$children"));
    pipeline.add(Aggregates.replaceWith("$children"));

    pipeline.add(projectFields());

    return pipeline;
}


 private Bson projectFields() {
    return Aggregates.project(new Document()
            .append("_id", new Document("$cond", Arrays.asList(
                    new Document("$ne", Arrays.asList("$_id", null)),
                    "$_id",
                    "$$REMOVE"
            )))
            .append("parentDesc", new Document("$cond", Arrays.asList(
                    new Document("$ne", Arrays.asList("$parent_desc", null)),
                    "$parent_desc",
                    "$$REMOVE"
            )))
            //... project other fields (working as expected)
            }

Note - this question gives me the raw result that I want when I run it as a mongo query.


Solution

  • the $addFields stage should look like {"children.parent_desc": "$parent_desc"} so the query becomes something like this. And in java code looks something like Bson addFieldsStage = Aggregates.addFields( new Field<>("children.parent_desc", "$parent_desc") );

    db.myCollection.aggregate([
      {
        $lookup: {
          from: "myCollection",
          localField: "parent_id",
          foreignField: "parent_id",
          as: "children"
        }
      },
      {
        $addFields: {
          "children.parent_desc": "$parent_desc"
        }
      },
      {
        $unwind: "$children"
      },
      {
        $replaceWith: "$children"
      }
    ])
    

    playground