首页 > 解决方案 > Spring mongo slice array in embedded document

问题描述

The slice method in aggreation for array within an embedded document is not working for me using spring mongo template.

Example:

Invoice collection:

{
  "reference_number": "aaa111",
  "historical_data": {
    "year": 2010,
    "data": [
      {
        "item_name": "Apple",
        "price": 50
      },
      {
        "item_name": "Book",
        "price": 200
      }
    ]
  }
}

Using mongoTemplate I would like to get only the historical data in slices.

For the arrays which needs to be sliced that appear directly under the root I had found a solution using aggregation Refer : Spring mongo repository slice

Applying a similar query for array in an embedded document returns an empty list even if there is data.

The query that I was trying was :

TypedAggregation<Invoice> agg = newAggregation(Invoice.class,
                match(where("reference_number").is(referenceNumber)),
                project.andExpression("historicalData.data").slice(limit, offset));
        AggregationResults<Invoice> result = mongoTemplate.aggregate(agg, Invoice.class, Invoice.class);

But this returns an empty list of data.

Is there any other alternative way to get the sliced result for arrays within an embedded document?

Invoice.java

@Data
@Document(collection = "invoice")
public class Invoice {

    @Id
    private String id;

    @NotEmpty
    @Indexed(unique = true)
    @Field("reference_number")
    private String referenceNumber = UUID.randomUUID().toString();

   @Valid
    @Field("historical_data")
    private HistoricalData historicalData = new HistoricalData();
}

HistoricalData:

@Data
public class HistoricalData {
    @NotEmpty
    @Field("year")
    private Intger year;
    @Valid
    @NotNull
    @Field("data")
    private List<InvoiceData> data = new LinkedList<>();
}

Note : I have also tried :

TypedAggregation<Invoice> agg = newAggregation(Invoice.class,
                match(where("reference_number").is(referenceNumber)),
                project.andExpression("historical_data.data").slice(limit, offset));
        AggregationResults<Invoice> result = mongoTemplate.aggregate(agg, Invoice.class, Invoice.class);

But this gave me a PropertyPathException.

Thanks in advance!!

标签: mongodbspring-dataspring-data-mongodbspring-mongodbmongotemplate

解决方案


经过一周的努力,我找到了解决方案:

ProjectionOperation project = project().and("historicalRevisionData.data").slice(limit, offset).as("historical_revision_data.data")
                .andInclude("id")
                .and("referenceNumber").as("reference_number");
TypedAggregation<Invoice> agg = newAggregation(Invoice.class,
                match(where("reference_number").is(referenceNumber)),
                project);
AggregationResults<TaxInvoice> aggregate = mongoTemplate.aggregate(agg, Invoice.class, Invoice.class);

希望这对其他人也有帮助。


推荐阅读