DATAMONGO-840 - Improve support for nested field references in SpEL expressions within Projections.
We now correctly add a compound expression that represents a field reference to the previous operation arguments if necessary. Original pull request: #118.
This commit is contained in:
committed by
Oliver Gierke
parent
99eefe0773
commit
88c968ad36
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013 the original author or authors.
|
||||
* Copyright 2013-2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -495,7 +495,7 @@ class SpelExpressionTransformer implements AggregationExpressionTransformer {
|
||||
|
||||
if (currentNode.hasfirstChildNotOfType(Indexer.class)) {
|
||||
// we have a property path expression like: foo.bar -> render as reference
|
||||
return context.getFieldReference().toString();
|
||||
return context.addToPreviousOrReturn(context.getFieldReference().toString());
|
||||
}
|
||||
|
||||
return context.addToPreviousOrReturn(currentNode.getValue());
|
||||
|
||||
@@ -782,6 +782,46 @@ public class AggregationTests {
|
||||
assertThat(String.valueOf(firstItem.get("_id")), is("u1"));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-840
|
||||
*/
|
||||
@Test
|
||||
public void shouldAggregateOrderDataToAnInvoice() {
|
||||
|
||||
mongoTemplate.dropCollection(Order.class);
|
||||
|
||||
double taxRate = 0.19;
|
||||
|
||||
LineItem product1 = new LineItem("1", "p1", 1.23);
|
||||
LineItem product2 = new LineItem("2", "p2", 0.87, 2);
|
||||
LineItem product3 = new LineItem("3", "p3", 5.33);
|
||||
|
||||
Order order = new Order("o4711", "c42", new Date()).addItem(product1).addItem(product2).addItem(product3);
|
||||
|
||||
mongoTemplate.save(order);
|
||||
|
||||
AggregationResults<Invoice> results = mongoTemplate.aggregate(newAggregation(Order.class, //
|
||||
match(where("id").is(order.getId())), unwind("items"), //
|
||||
project("id", "customerId", "items") //
|
||||
.andExpression("items.price * items.quantity").as("lineTotal"), //
|
||||
group("id") //
|
||||
.sum("lineTotal").as("netAmount") //
|
||||
.addToSet("items").as("items"), //
|
||||
project("id", "items", "netAmount") //
|
||||
.and("orderId").previousOperation() //
|
||||
.andExpression("netAmount * [0]", taxRate).as("taxAmount") //
|
||||
.andExpression("netAmount * (1 + [0])", taxRate).as("totalAmount") //
|
||||
), Invoice.class);
|
||||
|
||||
Invoice invoice = results.getUniqueMappedResult();
|
||||
|
||||
assertThat(invoice, is(notNullValue()));
|
||||
assertThat(invoice.getOrderId(), is(order.getId()));
|
||||
assertThat(invoice.getNetAmount(), is(closeTo(8.3, 000001)));
|
||||
assertThat(invoice.getTaxAmount(), is(closeTo(1.577, 000001)));
|
||||
assertThat(invoice.getTotalAmount(), is(closeTo(9.877, 000001)));
|
||||
}
|
||||
|
||||
private void assertLikeStats(LikeStats like, String id, long count) {
|
||||
|
||||
assertThat(like, is(notNullValue()));
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright 2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.mongodb.core.aggregation;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Thomas Darimont
|
||||
*/
|
||||
public class Invoice {
|
||||
|
||||
String orderId;
|
||||
|
||||
double taxAmount;
|
||||
|
||||
double netAmount;
|
||||
|
||||
double totalAmount;
|
||||
|
||||
List<LineItem> items;
|
||||
|
||||
public String getOrderId() {
|
||||
return orderId;
|
||||
}
|
||||
|
||||
public void setOrderId(String orderId) {
|
||||
this.orderId = orderId;
|
||||
}
|
||||
|
||||
public double getTaxAmount() {
|
||||
return taxAmount;
|
||||
}
|
||||
|
||||
public void setTaxAmount(double taxAmount) {
|
||||
this.taxAmount = taxAmount;
|
||||
}
|
||||
|
||||
public double getNetAmount() {
|
||||
return netAmount;
|
||||
}
|
||||
|
||||
public void setNetAmount(double netAmount) {
|
||||
this.netAmount = netAmount;
|
||||
}
|
||||
|
||||
public double getTotalAmount() {
|
||||
return totalAmount;
|
||||
}
|
||||
|
||||
public void setTotalAmount(double totalAmount) {
|
||||
this.totalAmount = totalAmount;
|
||||
}
|
||||
|
||||
public List<LineItem> getItems() {
|
||||
return items;
|
||||
}
|
||||
|
||||
public void setItems(List<LineItem> items) {
|
||||
this.items = items;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright 2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.mongodb.core.aggregation;
|
||||
|
||||
/**
|
||||
* @author Thomas Darimont
|
||||
*/
|
||||
public class LineItem {
|
||||
|
||||
final String id;
|
||||
|
||||
final String caption;
|
||||
|
||||
final double price;
|
||||
|
||||
int quantity = 1;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private LineItem() {
|
||||
this(null, null, 0.0, 0);
|
||||
}
|
||||
|
||||
public LineItem(String id, String caption, double price) {
|
||||
this.id = id;
|
||||
this.caption = caption;
|
||||
this.price = price;
|
||||
}
|
||||
|
||||
public LineItem(String id, String caption, double price, int quantity) {
|
||||
this(id, caption, price);
|
||||
this.quantity = quantity;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright 2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.mongodb.core.aggregation;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Thomas Darimont
|
||||
*/
|
||||
public class Order {
|
||||
|
||||
final String id;
|
||||
|
||||
final String customerId;
|
||||
|
||||
final Date orderDate;
|
||||
|
||||
final List<LineItem> items;
|
||||
|
||||
public Order(String id, String customerId, Date orderDate) {
|
||||
this(id, customerId, orderDate, new ArrayList<LineItem>());
|
||||
}
|
||||
|
||||
public Order(String id, String customerId, Date orderDate, List<LineItem> items) {
|
||||
this.id = id;
|
||||
this.customerId = customerId;
|
||||
this.orderDate = orderDate;
|
||||
this.items = items;
|
||||
}
|
||||
|
||||
public Order addItem(LineItem item) {
|
||||
|
||||
List<LineItem> newItems = new ArrayList<LineItem>(items != null ? items : Collections.<LineItem> emptyList());
|
||||
newItems.add(item);
|
||||
|
||||
return new Order(id, customerId, orderDate, newItems);
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getCustomerId() {
|
||||
return customerId;
|
||||
}
|
||||
|
||||
public Date getOrderDate() {
|
||||
return orderDate;
|
||||
}
|
||||
|
||||
public List<LineItem> getItems() {
|
||||
return items;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013 the original author or authors.
|
||||
* Copyright 2013-2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -21,6 +21,7 @@ import static org.junit.Assert.*;
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.springframework.data.mongodb.core.Person;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link SpelExpressionTransformer}.
|
||||
@@ -174,6 +175,26 @@ public class SpelExpressionTransformerUnitTests {
|
||||
is("{ \"$multiply\" : [ { \"$add\" : [ 1 , 42 , 1.2345]} , 23]}"));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-840
|
||||
*/
|
||||
@Test
|
||||
public void shouldRenderCompoundExpressionsWithIndexerAndFieldReference() {
|
||||
|
||||
Person person = new Person();
|
||||
person.setAge(10);
|
||||
assertThat(transform("[0].age + a.c", person), is("{ \"$add\" : [ 10 , \"$a.c\"]}"));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-840
|
||||
*/
|
||||
@Test
|
||||
public void shouldRenderCompoundExpressionsWithOnlyFieldReferences() {
|
||||
|
||||
assertThat(transform("a.b + a.c"), is("{ \"$add\" : [ \"$a.b\" , \"$a.c\"]}"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldRenderStringFunctions() {
|
||||
|
||||
|
||||
Reference in New Issue
Block a user