Spring Boot & MongoDB: Getting similar field values to a array

Viewed 100

I'm trying to get all the values of a specific field to a array.

This is the document structure:

 {

    "title": "testone",
    "docs": [
    {
        "fileId": "123",
        "fileName": "helloworld.txt"
    }, 
    {
        "fileId": "124",
        "fileName": "thisisalongtext.docx",
    }],
 }

Currently I've implemented following

Docs Class :

public class Docs implements Serializable {

    private String fileId;

    public String getFileId() {
        return fileId;
    }

    public void setFileId(String fileId) {
        this.fileId = fileId;
    }
}

Assignment Class:

@Document(collection = "assignemnt")
public class Assignment{

    private String title;
    private List<Docs> docs;

    public String getTitle() {
        return title;
    }


    public List<Docs> getDocs() {
        return docs;
    }

    public void setDocs(List<Docs> docs) {
        this.docs= docs;
    }

    @Override
    public String toString() {
        return "Assignment [title=" + title
            + ", docs=" + docs+ "]";
    }
}

RepositoryImplementation:

public List<Assignment> getAssignments(final String uID) {
    Query query = Query.query(Criteria.where(CREATEDBY).is(uID)
        .orOperator(Criteria.where("docs.0").exists(true),
            (Criteria.where("versionchecked").is(true))));
    return mongoTemplate.find(query, Assignment.class);
}

Current method returns the following response:

 {
            "title": "assignemnt123",
            "docs": [
                {
                    "fileId": "132"
                },
                {
                    "fileId": "123"
                },
                {
                    "fileId": "213"
                }
            ]       
        }

Response I want to create:

   {
                "title": "assignemnt123",
                "docs": [ "132" , "123", "213" ]       
   }

Is there a way to achieve this expected response?

1 Answers

Create a class that you need the desired output. You have the following classes already

@Data
@AllArgsConstructor
@NoArgsConstructor
class Docs {
  private String fileId;
  private String fileName;
}

@Data
@AllArgsConstructor
@NoArgsConstructor
class Assignment {
  private String title;
  private List<Docs> docs;
}

Additionally create the following class

@Data
@AllArgsConstructor
@NoArgsConstructor
class ConverterAssignment {
  private String title;
  private List<String> docs;
}

Then you can easily map.

List<Assignment> assignmentList =
        Arrays.asList(
            new Assignment(
                "testone",
                Arrays.asList(
                    new Docs("123", "helloworld1.txt"), new Docs("345", "helloworld2.txt"))),
            new Assignment(
                "testtwo",
                Arrays.asList(
                    new Docs("456", "helloworld3.txt"), new Docs("678", "helloworld4.txt"))));

This is the data you get from repository. With the result, you can use stream() easily. I have tested and worked fine.

List<ConverterAssignment> collect =
        assignmentList.stream()
            .map(
                m ->
                    new ConverterAssignment(
                        m.getTitle(),
                        m.getDocs().stream().map(d -> d.getFileId()).collect(Collectors.toList())))
            .collect(Collectors.toList());

If you want to use aggregations

db.collection.aggregate([
  {
    $project: {
      title: 1,
      docs: "$docs.fileId",
      _id: "$$REMOVE"
    }
  }
])

Working Mongo playground

@Autowired
private MongoTemplate mongoTemplate;

public List<ConverterAssignment> test(String value) {

    Aggregation aggregation = Aggregation.newAggregation(
            Aggregation.project("title").and("docs.fileId").as("docs")
    ).withOptions(AggregationOptions.builder().allowDiskUse(Boolean.TRUE).build());

    return mongoTemplate.aggregate(aggregation, mongoTemplate.getCollectionName(Assignment.class), ConverterAssignment.class).getMappedResults();

}

Note : The java aggregation code is not tested, but it was written based on working mongo playground

Related