How to Convert MongoDB Query to Spring Data Query

618 Views Asked by At

I'm trying to convert the following Mongo query for use with Spring data.

db.product.aggregate([
{$unwind: '$barcodes'},
{$project: {
    _id: 0, 
    productId: '$_id',
    productTitle: '$title',
    productVariation: '$variation', 
    barcode: '$barcodes'
}}])

This is what I've been trying so far. It returns the aggregation, but with null values:

UnwindOperation unwindOperation = Aggregation.unwind("barcodes");

ProjectionOperation projectStage = Aggregation.project().and("productId").as("_id").and("productTitle")
  .as("title")
  .and("productVariation").as("variation")
  .and("barcodeTitle").as("barcodes.title")
  .and("barcodeValue").as("barcodes.value")
  .and("barcodeType").as("barcodes.type")
  .and("codeStandard").as("barcodes.codeStandard")
  .and("quantity").as("barcodes.quantity")
  .and("status").as("barcodes.status");

SortOperation sortOperation = Aggregation.sort(Sort.by(Sort.Direction.DESC, "title"));

Aggregation agg = Aggregation.newAggregation(unwindOperation, projectStage, sortOperation);

AggregationResults<BarcodeAggregateList> results = mongoTemplate.aggregate(agg, "product", BarcodeAggregateList.class);

What it is returning:

return example

The class I am mapping to (has getters/setters):

public class BarcodeAggregateList {
   private String productId;
   private String productTitle;
   private String productVariation;
   private String barcodeTitle;
   private String barcodeValue;
   private String barcodeType;
   private String codeStandard;
   private int quantity;
   private String status;
}

Product class that the data is coming from:

public class Product implements Serializable {
   private static final long serialVersionUID = -998149317494604215L;
   private String id;
   private String title;
   private String description;
   private String SKU;
   private double cost;
   private double retailPrice;
   private String status;
   private LocalDate launchDate;
   private LocalDate discontinueDate;
   private String discontinueReason;
   private String salesChannel;
   private List<Barcode> barcodes;
   private ProductVariation variation;
   private List<Supplier> supplier;
   private Product parentProduct;
   private boolean updateChildren;
   private Label label;
   private int secondaryStockLevel;
   private int primaryStockLevel;
   private Date createdDate;
   private Date modifiedDate;
   private List<Dimension> dimensions;
   private boolean isDeleted = false;
}

Barcode class

public class Barcode {
    private String type;
    private String title;
    private String value;
    private String status;
    private String codeStandard;
    private int quantity;
}

I appreciate any help with this or resources to help me better understand how to perform these types of conversions.

For anyone trying to solve similar issues, I've found the following resources somewhat helpful:

1

There are 1 best solutions below

1
On BEST ANSWER

BarcodeAggregateList class fields are null because there is a minor issue in ProjectionOperation's and() and as() methods. The correct syntax is

Aggregation.project().and(SOURCE_FIELD).as(TARGET_FIELD)

You have written and("productId").as("_id") , which is wrong

You need to write this as and("_id").as("productId") , because source field is _id

complete code:

UnwindOperation unwindOperation = Aggregation.unwind("barcodes");

ProjectionOperation projectStage = Aggregation.project()
        .and("_id").as("productId")
        .and("title").as("productTitle")
        .and("variation").as("productVariation")
        .and("barcodes.title").as("barcodeTitle")
        .and("barcodes.value").as("barcodeValue")
        .and("barcodes.type").as("barcodeType")
        .and("barcodes.codeStandard").as("codeStandard")
        .and("barcodes.quantity").as("quantity")
        .and("barcodes.status").as("status");

SortOperation sortOperation = Aggregation.sort(Sort.by(Sort.Direction.DESC, "productTitle"));

Aggregation agg = Aggregation.newAggregation(unwindOperation, projectStage, sortOperation);

AggregationResults<BarcodeAggregateList> results = mongoTemplate.aggregate(agg, "product", BarcodeAggregateList.class);