From 37b86f21917af6c21787c0d378fd9320382ca1e0 Mon Sep 17 00:00:00 2001 From: Robin Bygrave Date: Tue, 8 Mar 2016 00:00:02 +1300 Subject: [PATCH] #589 - ElasticSearch - refactor to DocQueryContext --- src/main/java/com/avaje/ebean/Query.java | 5 - .../ebeaninternal/api/SpiExpression.java | 4 +- .../ebeaninternal/api/SpiExpressionList.java | 6 + .../com/avaje/ebeaninternal/api/SpiQuery.java | 7 - .../expression/AllEqualsExpression.java | 15 +- .../server/expression/BetweenExpression.java | 2 +- .../expression/BetweenPropertyExpression.java | 7 +- .../CaseInsensitiveEqualExpression.java | 4 +- .../expression/DefaultExampleExpression.java | 8 +- .../expression/DefaultExpressionList.java | 18 +- .../server/expression/DocQueryContext.java | 93 ++++ .../expression/ElasticExpressionContext.java | 430 ------------------ .../expression/ExistsQueryExpression.java | 2 +- .../server/expression/IdExpression.java | 2 +- .../server/expression/IdInExpression.java | 2 +- .../server/expression/InExpression.java | 4 +- .../server/expression/InQueryExpression.java | 2 +- .../server/expression/JsonPathExpression.java | 3 +- .../server/expression/JunctionExpression.java | 9 +- .../server/expression/LikeExpression.java | 32 +- .../server/expression/LogicExpression.java | 10 +- .../server/expression/NoopExpression.java | 2 +- .../server/expression/NotExpression.java | 8 +- .../server/expression/NullExpression.java | 2 +- .../server/expression/RawExpression.java | 4 +- .../server/expression/SimpleExpression.java | 4 +- .../server/querydefn/DefaultOrmQuery.java | 66 +-- .../server/querydefn/OrmQueryDetail.java | 67 +-- .../server/querydefn/OrmQueryProperties.java | 2 +- .../server/expression/BaseElasticTest.java | 19 - .../SimpleExpressionElasticTest.java | 22 - .../querydefn/DefaultOrmQueryElasticTest.java | 82 ---- 32 files changed, 155 insertions(+), 788 deletions(-) create mode 100644 src/main/java/com/avaje/ebeaninternal/server/expression/DocQueryContext.java delete mode 100644 src/main/java/com/avaje/ebeaninternal/server/expression/ElasticExpressionContext.java delete mode 100644 src/test/java/com/avaje/ebeaninternal/server/expression/BaseElasticTest.java delete mode 100644 src/test/java/com/avaje/ebeaninternal/server/expression/SimpleExpressionElasticTest.java delete mode 100644 src/test/java/com/avaje/ebeaninternal/server/querydefn/DefaultOrmQueryElasticTest.java diff --git a/src/main/java/com/avaje/ebean/Query.java b/src/main/java/com/avaje/ebean/Query.java index 363f2c90e..a1fc3fc04 100644 --- a/src/main/java/com/avaje/ebean/Query.java +++ b/src/main/java/com/avaje/ebean/Query.java @@ -1373,9 +1373,4 @@ public interface Query { */ Set validate(); - /** - * Return the query in JSON form for ElasticSearch doc store. - */ - String asElasticQuery(); - } diff --git a/src/main/java/com/avaje/ebeaninternal/api/SpiExpression.java b/src/main/java/com/avaje/ebeaninternal/api/SpiExpression.java index 59aec8e2b..a500974dd 100644 --- a/src/main/java/com/avaje/ebeaninternal/api/SpiExpression.java +++ b/src/main/java/com/avaje/ebeaninternal/api/SpiExpression.java @@ -3,7 +3,7 @@ package com.avaje.ebeaninternal.api; import com.avaje.ebean.Expression; import com.avaje.ebean.event.BeanQueryRequest; import com.avaje.ebeaninternal.server.deploy.BeanDescriptor; -import com.avaje.ebeaninternal.server.expression.ElasticExpressionContext; +import com.avaje.ebeaninternal.server.expression.DocQueryContext; import java.io.IOException; @@ -16,7 +16,7 @@ public interface SpiExpression extends Expression { /** * Write the expression as an elastic search expression. */ - void writeElastic(ElasticExpressionContext context) throws IOException; + void writeDocQuery(DocQueryContext context) throws IOException; /** * Process "Many" properties populating ManyWhereJoins. diff --git a/src/main/java/com/avaje/ebeaninternal/api/SpiExpressionList.java b/src/main/java/com/avaje/ebeaninternal/api/SpiExpressionList.java index de075203c..c035d1b55 100644 --- a/src/main/java/com/avaje/ebeaninternal/api/SpiExpressionList.java +++ b/src/main/java/com/avaje/ebeaninternal/api/SpiExpressionList.java @@ -1,7 +1,9 @@ package com.avaje.ebeaninternal.api; import com.avaje.ebean.ExpressionList; +import com.avaje.ebeaninternal.server.expression.DocQueryContext; +import java.io.IOException; import java.util.List; /** @@ -24,4 +26,8 @@ public interface SpiExpressionList extends ExpressionList, SpiExpression { */ boolean isEmpty(); + /** + * Write the top level where expressions taking into account possible extra idEquals expression. + */ + void writeDocQuery(DocQueryContext context, SpiExpression idEquals) throws IOException; } diff --git a/src/main/java/com/avaje/ebeaninternal/api/SpiQuery.java b/src/main/java/com/avaje/ebeaninternal/api/SpiQuery.java index df2c81301..0aeaad4c0 100644 --- a/src/main/java/com/avaje/ebeaninternal/api/SpiQuery.java +++ b/src/main/java/com/avaje/ebeaninternal/api/SpiQuery.java @@ -16,12 +16,10 @@ import com.avaje.ebeaninternal.server.autotune.ProfilingListener; import com.avaje.ebeaninternal.server.deploy.BeanDescriptor; import com.avaje.ebeaninternal.server.deploy.BeanPropertyAssocMany; import com.avaje.ebeaninternal.server.deploy.TableJoin; -import com.avaje.ebeaninternal.server.expression.ElasticExpressionContext; import com.avaje.ebeaninternal.server.query.CancelableQuery; import com.avaje.ebeaninternal.server.querydefn.NaturalKeyBindParam; import com.avaje.ebeaninternal.server.querydefn.OrmQueryDetail; -import java.io.IOException; import java.sql.Timestamp; import java.util.List; import java.util.Set; @@ -130,11 +128,6 @@ public interface SpiQuery extends Query { } } - /** - * Write the query as an elastic search query. - */ - void writeElastic(ElasticExpressionContext context) throws IOException; - /** * Return true if AutoTune should be attempted on this query. */ diff --git a/src/main/java/com/avaje/ebeaninternal/server/expression/AllEqualsExpression.java b/src/main/java/com/avaje/ebeaninternal/server/expression/AllEqualsExpression.java index 57acd03ce..b21d18816 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/expression/AllEqualsExpression.java +++ b/src/main/java/com/avaje/ebeaninternal/server/expression/AllEqualsExpression.java @@ -28,19 +28,8 @@ class AllEqualsExpression extends NonPrepareExpression { } @Override - public void writeElastic(ElasticExpressionContext context) throws IOException { - - context.writeBoolMustStart(); - for (Map.Entry entry : propMap.entrySet()) { - Object value = entry.getValue(); - String propName = entry.getKey(); - if (value == null) { - context.writeExists(false, propName); - } else { - context.writeTerm(propName, value); - } - } - context.writeBoolEnd(); + public void writeDocQuery(DocQueryContext context) throws IOException { + context.writeAllEquals(propMap); } @Override diff --git a/src/main/java/com/avaje/ebeaninternal/server/expression/BetweenExpression.java b/src/main/java/com/avaje/ebeaninternal/server/expression/BetweenExpression.java index 871271d9b..255fd117f 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/expression/BetweenExpression.java +++ b/src/main/java/com/avaje/ebeaninternal/server/expression/BetweenExpression.java @@ -23,7 +23,7 @@ class BetweenExpression extends AbstractExpression { } @Override - public void writeElastic(ElasticExpressionContext context) throws IOException { + public void writeDocQuery(DocQueryContext context) throws IOException { context.writeRange(propName, Op.GT_EQ, valueLow, Op.LT_EQ, valueHigh); } diff --git a/src/main/java/com/avaje/ebeaninternal/server/expression/BetweenPropertyExpression.java b/src/main/java/com/avaje/ebeaninternal/server/expression/BetweenPropertyExpression.java index 86a032d26..133904a84 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/expression/BetweenPropertyExpression.java +++ b/src/main/java/com/avaje/ebeaninternal/server/expression/BetweenPropertyExpression.java @@ -34,12 +34,11 @@ class BetweenPropertyExpression extends NonPrepareExpression { } @Override - public void writeElastic(ElasticExpressionContext context) throws IOException { - - context.writeBoolMustStart(); + public void writeDocQuery(DocQueryContext context) throws IOException { + context.startBoolMust(); context.writeSimple(Op.LT_EQ, lowProperty, value); context.writeSimple(Op.GT_EQ, highProperty, value); - context.writeBoolEnd(); + context.endBool(); } @Override diff --git a/src/main/java/com/avaje/ebeaninternal/server/expression/CaseInsensitiveEqualExpression.java b/src/main/java/com/avaje/ebeaninternal/server/expression/CaseInsensitiveEqualExpression.java index ea2c99f15..399e79d42 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/expression/CaseInsensitiveEqualExpression.java +++ b/src/main/java/com/avaje/ebeaninternal/server/expression/CaseInsensitiveEqualExpression.java @@ -19,8 +19,8 @@ class CaseInsensitiveEqualExpression extends AbstractExpression { } @Override - public void writeElastic(ElasticExpressionContext context) throws IOException { - context.writeIEqual(propName, value); + public void writeDocQuery(DocQueryContext context) throws IOException { + context.writeIEqualTo(propName, value); } @Override diff --git a/src/main/java/com/avaje/ebeaninternal/server/expression/DefaultExampleExpression.java b/src/main/java/com/avaje/ebeaninternal/server/expression/DefaultExampleExpression.java index 4ae366686..020fc457f 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/expression/DefaultExampleExpression.java +++ b/src/main/java/com/avaje/ebeaninternal/server/expression/DefaultExampleExpression.java @@ -96,13 +96,13 @@ public class DefaultExampleExpression implements SpiExpression, ExampleExpressio } @Override - public void writeElastic(ElasticExpressionContext context) throws IOException { + public void writeDocQuery(DocQueryContext context) throws IOException { if (!list.isEmpty()) { - context.writeBoolMustStart(); + context.startBoolMust(); for (SpiExpression expr : list) { - expr.writeElastic(context); + expr.writeDocQuery(context); } - context.writeBoolEnd(); + context.endBool(); } } diff --git a/src/main/java/com/avaje/ebeaninternal/server/expression/DefaultExpressionList.java b/src/main/java/com/avaje/ebeaninternal/server/expression/DefaultExpressionList.java index b612b46e2..2bf3a44cb 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/expression/DefaultExpressionList.java +++ b/src/main/java/com/avaje/ebeaninternal/server/expression/DefaultExpressionList.java @@ -61,29 +61,29 @@ public class DefaultExpressionList implements SpiExpressionList { } @Override - public void writeElastic(ElasticExpressionContext context) throws IOException { - writeElastic(context, null); + public void writeDocQuery(DocQueryContext context) throws IOException { + writeDocQuery(context, null); } - public void writeElastic(ElasticExpressionContext context, SpiExpression idEquals) throws IOException { + public void writeDocQuery(DocQueryContext context, SpiExpression idEquals) throws IOException { int size = list.size(); if (size == 1 && idEquals == null) { // only 1 expression - skip bool must - list.get(0).writeElastic(context); + list.get(0).writeDocQuery(context); } else if (size == 0 && idEquals != null) { // only idEquals - skip bool must - idEquals.writeElastic(context); + idEquals.writeDocQuery(context); } else { // bool must wrap all the children - context.writeBoolMustStart(); + context.startBoolMust(); if (idEquals != null) { - idEquals.writeElastic(context); + idEquals.writeDocQuery(context); } for (int i = 0; i < size; i++) { - list.get(i).writeElastic(context); + list.get(i).writeDocQuery(context); } - context.writeBoolEnd(); + context.endBool(); } } diff --git a/src/main/java/com/avaje/ebeaninternal/server/expression/DocQueryContext.java b/src/main/java/com/avaje/ebeaninternal/server/expression/DocQueryContext.java new file mode 100644 index 000000000..ffea20340 --- /dev/null +++ b/src/main/java/com/avaje/ebeaninternal/server/expression/DocQueryContext.java @@ -0,0 +1,93 @@ +package com.avaje.ebeaninternal.server.expression; + +import com.avaje.ebean.LikeType; + +import java.io.IOException; +import java.util.List; +import java.util.Map; + +/** + * Context for writing a doc store query. + */ +public interface DocQueryContext { + + /** + * Start a conjunction or disjunction. + */ + void startBool(boolean conjunction) throws IOException; + + /** + * Start a conjunction. + */ + void startBoolMust() throws IOException; + + /** + * Start a boolean NOT. + */ + void startBoolMustNot() throws IOException; + + /** + * End a bool expression/group. + */ + void endBool() throws IOException; + + /** + * Write a equalTo expression. + */ + void writeEqualTo(String propertyName, Object value) throws IOException; + + /** + * Write a case insensitive equalTo expression. + */ + void writeIEqualTo(String propName, String value) throws IOException; + + /** + * Write a range operation with one value. + */ + void writeRange(String propertyName, String rangeType, Object value) throws IOException; + + /** + * Write a range operation with a lower and upper values. + */ + void writeRange(String propertyName, Op lowOp, Object valueLow, Op highOp, Object valueHigh) throws IOException; + + /** + * Write an In expression. + */ + void writeIn(String propertyName, Object[] values, boolean not) throws IOException; + + /** + * Write an Id in expression. + */ + void writeIds(List idList) throws IOException; + + /** + * Write an Id equals expression. + */ + void writeId(Object value) throws IOException; + + /** + * Write a raw expression with bind values (might not be supported). + */ + void writeRaw(String raw, Object[] values) throws IOException; + + /** + * Write an exists expression. + */ + void writeExists(boolean notNull, String propertyName) throws IOException; + + /** + * Write one of the base expressions. + */ + void writeSimple(Op type, String propertyName, Object value) throws IOException; + + /** + * Write an all equals expression. + */ + void writeAllEquals(Map propMap) throws IOException; + + /** + * Write a Like expression. + */ + void writeLike(String propName, String val, LikeType type, boolean caseInsensitive) throws IOException; +} diff --git a/src/main/java/com/avaje/ebeaninternal/server/expression/ElasticExpressionContext.java b/src/main/java/com/avaje/ebeaninternal/server/expression/ElasticExpressionContext.java deleted file mode 100644 index b60a48e9f..000000000 --- a/src/main/java/com/avaje/ebeaninternal/server/expression/ElasticExpressionContext.java +++ /dev/null @@ -1,430 +0,0 @@ -package com.avaje.ebeaninternal.server.expression; - -import com.avaje.ebean.OrderBy; -import com.avaje.ebean.plugin.BeanType; -import com.avaje.ebean.plugin.ExpressionPath; -import com.avaje.ebean.text.json.JsonContext; -import com.avaje.ebeaninternal.server.query.SplitName; -import com.fasterxml.jackson.core.JsonGenerator; - -import java.io.IOException; -import java.io.StringWriter; -import java.util.ArrayList; -import java.util.List; - -/** - * Context for writing elastic search expressions. - */ -public class ElasticExpressionContext { - - public static final String MUST = "must"; - public static final String SHOULD = "should"; - public static final String MUST_NOT = "must_not"; - public static final String BOOL = "bool"; - public static final String TERM = "term"; - public static final String RANGE = "range"; - public static final String TERMS = "terms"; - public static final String IDS = "ids"; - public static final String VALUES = "values"; - public static final String PREFIX = "prefix"; - public static final String MATCH = "match"; - public static final String WILDCARD = "wildcard"; - public static final String EXISTS = "exists"; - public static final String FIELD = "field"; - - private final JsonContext jsonContext; - - private final JsonGenerator json; - - private final StringWriter writer; - - private final BeanType desc; - - private String currentNestedPath; - - /** - * Construct given the JSON generator and root bean type. - */ - public ElasticExpressionContext(JsonContext jsonContext, BeanType desc) { - this.jsonContext = jsonContext; - this.desc = desc; - this.writer = new StringWriter(200); - this.json = jsonContext.createGenerator(writer); - } - - /** - * Return the JsonGenerator. - */ - public JsonGenerator json() { - return json; - } - - /** - * Flush the JsonGenerator buffer. - */ - public String flush() throws IOException { - endNested(); - json.flush(); - return writer.toString(); - } - - /** - * Return true if the path contains a many. - */ - public boolean containsMany(String path) { - ExpressionPath elPath = desc.getExpressionPath(path); - return elPath == null || elPath.containsMany(); - } - - /** - * Return an associated 'raw' property given the property name. - * This just returns the original propertyName if no 'raw' property is mapped. - */ - private String rawProperty(String propertyName) { - return desc.docStore().rawProperty(propertyName); - } - - /** - * Start Bool MUST or SHOULD. - *

- * If conjunction is true then MUST(and) and if false is SHOULD(or). - */ - public void writeBoolStart(boolean conjunction) throws IOException { - writeBoolStart((conjunction) ? MUST : SHOULD); - } - - /** - * Start Bool MUST. - */ - public void writeBoolMustStart() throws IOException { - writeBoolStart(MUST); - } - - /** - * Start Bool MUST_NOT. - */ - public void writeBoolMustNotStart() throws IOException { - writeBoolStart(MUST_NOT); - } - - /** - * Start a Bool expression list with the given type (MUST, MUST_NOT, SHOULD). - */ - private void writeBoolStart(String type) throws IOException { - endNested(); - json.writeStartObject(); - json.writeObjectFieldStart(BOOL); - json.writeArrayFieldStart(type); - } - - /** - * Write the end of a Bool expression list. - */ - public void writeBoolEnd() throws IOException { - json.writeEndArray(); - json.writeEndObject(); - json.writeEndObject(); - } - - /** - * Write a term expression. - */ - public void writeTerm(String propertyName, Object value) throws IOException { - - // prepareNested on propertyName and expression uses raw - prepareNestedPath(propertyName); - writeRawExpression(TERM, rawProperty(propertyName), value); - } - - /** - * Write a range expression with a single value. - */ - public void writeRange(String propertyName, String rangeType, Object value) throws IOException { - - prepareNestedPath(propertyName); - json.writeStartObject(); - json.writeObjectFieldStart(RANGE); - json.writeObjectFieldStart(rawProperty(propertyName)); - json.writeFieldName(rangeType); - jsonContext.writeScalar(json, value); - json.writeEndObject(); - json.writeEndObject(); - json.writeEndObject(); - } - - /** - * Write a range expression with a low and high value. - */ - public void writeRange(String propertyName, Op lowOp, Object valueLow, Op highOp, Object valueHigh) throws IOException { - - prepareNestedPath(propertyName); - json.writeStartObject(); - json.writeObjectFieldStart(RANGE); - json.writeObjectFieldStart(rawProperty(propertyName)); - json.writeFieldName(lowOp.docExp()); - jsonContext.writeScalar(json, valueLow); - json.writeFieldName(highOp.docExp()); - jsonContext.writeScalar(json, valueHigh); - json.writeEndObject(); - json.writeEndObject(); - json.writeEndObject(); - } - - /** - * Write a terms expression. - */ - public void writeTerms(String propertyName, Object[] values) throws IOException { - - prepareNestedPath(propertyName); - json.writeStartObject(); - json.writeObjectFieldStart(TERMS); - json.writeArrayFieldStart(rawProperty(propertyName)); - for (Object value : values) { - jsonContext.writeScalar(json, value); - } - json.writeEndArray(); - json.writeEndObject(); - json.writeEndObject(); - } - - /** - * Write an Ids expression. - */ - public void writeIds(List idList) throws IOException { - - endNested(); - json.writeStartObject(); - json.writeObjectFieldStart(IDS); - json.writeArrayFieldStart(VALUES); - for (Object id : idList) { - jsonContext.writeScalar(json, id); - } - json.writeEndArray(); - json.writeEndObject(); - json.writeEndObject(); - } - - /** - * Write an Id expression. - */ - public void writeId(Object value) throws IOException { - - List ids = new ArrayList(1); - ids.add(value); - writeIds(ids); - } - - /** - * Write a prefix expression. - */ - public void writeStartsWith(String propertyName, String value) throws IOException { - // use analysed field - writeRawWithPrepareNested(PREFIX, propertyName, value.toLowerCase()); - } - - /** - * Suffix expression not supported yet. - */ - public void writeEndsWith(String propertyName, String value) throws IOException { - // use analysed field - // this will likely be slow - best to avoid if you can - writeWildcard(propertyName, "*" + value.toLowerCase()); - } - - /** - * Write a match expression. - */ - public void writeContains(String propertyName, String value) throws IOException { - // use analysed field - writeWildcard(propertyName, "*" + value.toLowerCase() + "*"); - } - - /** - * Write a wildcard expression. - */ - public void writeLike(String propertyName, String value) throws IOException { - // use analysed field - String val = value.toLowerCase(); - // replace SQL wildcard characters with ElasticSearch ones - val = val.replace('_', '?'); - val = val.replace('%', '*'); - writeRawWithPrepareNested(WILDCARD, propertyName, val); - } - - /** - * Write case-insensitive equal to. - */ - public void writeIEqual(String propName, String value) throws IOException { - - String[] values = value.toLowerCase().split(" "); - if (values.length == 1) { - writeMatch(propName, value); - } else { - // Boolean AND all the terms together - writeBoolStart(true); - for (String val : values) { - writeMatch(propName, val); - } - writeBoolEnd(); - } - } - - /** - * Write a prefix expression. - */ - public void writeMatch(String propertyName, String value) throws IOException { - // use analysed field - writeRawWithPrepareNested(MATCH, propertyName, value.toLowerCase()); - } - - /** - * Write a wildcard expression. - */ - public void writeWildcard(String propertyName, String value) throws IOException { - writeRawWithPrepareNested(WILDCARD, propertyName, value); - } - - /** - * Write raw JSON to the query buffer. - */ - public void writeRaw(String jsonExpression) throws IOException { - json.writeRaw(jsonExpression); - } - - /** - * Write an exists expression. - */ - public void writeExists(boolean notNull, String propertyName) throws IOException { - - // prepareNestedPath prior to BoolMustNotStart - prepareNestedPath(propertyName); - if (!notNull) { - writeBoolMustNotStart(); - } - writeExists(propertyName); - if (!notNull) { - writeBoolEnd(); - } - } - - private void writeExists(String propertyName) throws IOException { - writeRawExpression(EXISTS, FIELD, propertyName); - } - - /** - * Write with prepareNestedPath() on the propertyName - */ - private void writeRawWithPrepareNested(String type, String propertyName, Object value) throws IOException { - - prepareNestedPath(propertyName); - writeRawExpression(type, propertyName, value); - } - - /** - * Write raw. prepareNestedPath() should already be done. - */ - private void writeRawExpression(String type, String propertyName, Object value) throws IOException { - - json.writeStartObject(); - json.writeObjectFieldStart(type); - json.writeFieldName(propertyName); - jsonContext.writeScalar(json, value); - json.writeEndObject(); - json.writeEndObject(); - } - - /** - * Write an expression for the core operations. - */ - public void writeSimple(Op type, String propertyName, Object value) throws IOException { - - // prepareNested prior to boolMustNotStart - prepareNestedPath(propertyName); - switch (type) { - case EQ: - writeTerm(propertyName, value); - break; - case NOT_EQ: - writeBoolMustNotStart(); - writeTerm(propertyName, value); - writeBoolEnd(); - break; - case EXISTS: - writeExists(true, propertyName); - break; - case NOT_EXISTS: - writeExists(false, propertyName); - break; - case BETWEEN: - throw new IllegalStateException("BETWEEN Not expected in SimpleExpression?"); - - default: - writeRange(propertyName, type.docExp(), value); - } - } - - /** - * Write the query sort. - */ - public void writeOrderBy(OrderBy orderBy) throws IOException { - - if (orderBy != null && !orderBy.isEmpty()) { - json.writeArrayFieldStart("sort"); - for (OrderBy.Property property : orderBy.getProperties()) { - json.writeStartObject(); - json.writeObjectFieldStart(rawProperty(property.getProperty())); - json.writeStringField("order", property.isAscending() ? "asc" : "desc"); - json.writeEndObject(); - json.writeEndObject(); - } - json.writeEndArray(); - } - } - - /** - * Check if we need to start a nested path filter and do so if required. - */ - private void prepareNestedPath(String propName) throws IOException { - ExpressionPath exprPath = desc.getExpressionPath(propName); - if (exprPath != null && exprPath.containsMany()) { - String[] manyPath = SplitName.splitBegin(propName); - startNested(manyPath[0]); - } else { - endNested(); - } - } - - /** - * Start a nested path filter. - */ - private void startNested(String nestedPath) throws IOException { - - if (currentNestedPath != null) { - if (currentNestedPath.equals(nestedPath)) { - // just add to currentNestedPath - return; - } else { - // end the prior one as this is different - endNested(); - } - } - currentNestedPath = nestedPath; - - json.writeStartObject(); - json.writeObjectFieldStart("nested"); - json.writeStringField("path", nestedPath); - json.writeFieldName("filter"); - } - - /** - * End a nested path filter if one is still open. - */ - private void endNested() throws IOException { - if (currentNestedPath != null) { - currentNestedPath = null; - json.writeEndObject(); - json.writeEndObject(); - } - } - -} diff --git a/src/main/java/com/avaje/ebeaninternal/server/expression/ExistsQueryExpression.java b/src/main/java/com/avaje/ebeaninternal/server/expression/ExistsQueryExpression.java index fdaf30d2e..1a2992d28 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/expression/ExistsQueryExpression.java +++ b/src/main/java/com/avaje/ebeaninternal/server/expression/ExistsQueryExpression.java @@ -39,7 +39,7 @@ class ExistsQueryExpression implements SpiExpression, UnsupportedDocStoreExpress } @Override - public void writeElastic(ElasticExpressionContext context) throws IOException { + public void writeDocQuery(DocQueryContext context) throws IOException { throw new IllegalStateException("Not supported"); } diff --git a/src/main/java/com/avaje/ebeaninternal/server/expression/IdExpression.java b/src/main/java/com/avaje/ebeaninternal/server/expression/IdExpression.java index dd9ae9504..b55fd7952 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/expression/IdExpression.java +++ b/src/main/java/com/avaje/ebeaninternal/server/expression/IdExpression.java @@ -23,7 +23,7 @@ class IdExpression extends NonPrepareExpression implements SpiExpression { } @Override - public void writeElastic(ElasticExpressionContext context) throws IOException { + public void writeDocQuery(DocQueryContext context) throws IOException { context.writeId(value); } diff --git a/src/main/java/com/avaje/ebeaninternal/server/expression/IdInExpression.java b/src/main/java/com/avaje/ebeaninternal/server/expression/IdInExpression.java index 0fa095620..c63fc1f38 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/expression/IdInExpression.java +++ b/src/main/java/com/avaje/ebeaninternal/server/expression/IdInExpression.java @@ -29,7 +29,7 @@ public class IdInExpression extends NonPrepareExpression { } @Override - public void writeElastic(ElasticExpressionContext context) throws IOException { + public void writeDocQuery(DocQueryContext context) throws IOException { context.writeIds(idList); } diff --git a/src/main/java/com/avaje/ebeaninternal/server/expression/InExpression.java b/src/main/java/com/avaje/ebeaninternal/server/expression/InExpression.java index be11282eb..1ed7ef702 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/expression/InExpression.java +++ b/src/main/java/com/avaje/ebeaninternal/server/expression/InExpression.java @@ -30,8 +30,8 @@ class InExpression extends AbstractExpression { } @Override - public void writeElastic(ElasticExpressionContext context) throws IOException { - context.writeTerms(propName, values); + public void writeDocQuery(DocQueryContext context) throws IOException { + context.writeIn(propName, values, not); } @Override diff --git a/src/main/java/com/avaje/ebeaninternal/server/expression/InQueryExpression.java b/src/main/java/com/avaje/ebeaninternal/server/expression/InQueryExpression.java index 6914e69bf..a486b558c 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/expression/InQueryExpression.java +++ b/src/main/java/com/avaje/ebeaninternal/server/expression/InQueryExpression.java @@ -41,7 +41,7 @@ class InQueryExpression extends AbstractExpression implements UnsupportedDocStor } @Override - public void writeElastic(ElasticExpressionContext context) throws IOException { + public void writeDocQuery(DocQueryContext context) throws IOException { throw new IllegalStateException("Not supported"); } diff --git a/src/main/java/com/avaje/ebeaninternal/server/expression/JsonPathExpression.java b/src/main/java/com/avaje/ebeaninternal/server/expression/JsonPathExpression.java index 7249a1c17..f89905f59 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/expression/JsonPathExpression.java +++ b/src/main/java/com/avaje/ebeaninternal/server/expression/JsonPathExpression.java @@ -60,8 +60,7 @@ class JsonPathExpression extends AbstractExpression { } @Override - public void writeElastic(ElasticExpressionContext context) throws IOException { - + public void writeDocQuery(DocQueryContext context) throws IOException { String fullName = propName + "." + path; if (operator == Op.BETWEEN) { context.writeRange(fullName, Op.GT_EQ, value, Op.LT_EQ, upperValue); diff --git a/src/main/java/com/avaje/ebeaninternal/server/expression/JunctionExpression.java b/src/main/java/com/avaje/ebeaninternal/server/expression/JunctionExpression.java index 6ed39b1b5..7a3249c29 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/expression/JunctionExpression.java +++ b/src/main/java/com/avaje/ebeaninternal/server/expression/JunctionExpression.java @@ -100,14 +100,13 @@ abstract class JunctionExpression implements Junction, SpiExpression, Expr } @Override - public void writeElastic(ElasticExpressionContext context) throws IOException { - - context.writeBoolStart(!disjunction); + public void writeDocQuery(DocQueryContext context) throws IOException { + context.startBool(!disjunction); List list = exprList.internalList(); for (int i = 0; i < list.size(); i++) { - list.get(i).writeElastic(context); + list.get(i).writeDocQuery(context); } - context.writeBoolEnd(); + context.endBool(); } @Override diff --git a/src/main/java/com/avaje/ebeaninternal/server/expression/LikeExpression.java b/src/main/java/com/avaje/ebeaninternal/server/expression/LikeExpression.java index f7f4033c2..91bac41b0 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/expression/LikeExpression.java +++ b/src/main/java/com/avaje/ebeaninternal/server/expression/LikeExpression.java @@ -26,36 +26,8 @@ class LikeExpression extends AbstractExpression { } @Override - public void writeElastic(ElasticExpressionContext context) throws IOException { - - switch (type) { - case RAW: - context.writeLike(propName, val); - break; - - case STARTS_WITH: - context.writeStartsWith(propName, val); - break; - - case ENDS_WITH: - context.writeEndsWith(propName, val); - break; - - case CONTAINS: - context.writeContains(propName, val); - break; - - case EQUAL_TO: - if (caseInsensitive) { - context.writeIEqual(propName, val); - } else { - context.writeTerm(propName, val); - } - break; - - default: - throw new RuntimeException("LikeType " + type + " missed?"); - } + public void writeDocQuery(DocQueryContext context) throws IOException { + context.writeLike(propName, val, type, caseInsensitive); } @Override diff --git a/src/main/java/com/avaje/ebeaninternal/server/expression/LogicExpression.java b/src/main/java/com/avaje/ebeaninternal/server/expression/LogicExpression.java index 6f750f42c..b29f848a0 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/expression/LogicExpression.java +++ b/src/main/java/com/avaje/ebeaninternal/server/expression/LogicExpression.java @@ -63,13 +63,13 @@ abstract class LogicExpression implements SpiExpression { } @Override - public void writeElastic(ElasticExpressionContext context) throws IOException { + public void writeDocQuery(DocQueryContext context) throws IOException { boolean conjunction = joinType.equals(AND); - context.writeBoolStart(conjunction); - expOne.writeElastic(context); - expTwo.writeElastic(context); - context.writeBoolEnd(); + context.startBool(conjunction); + expOne.writeDocQuery(context); + expTwo.writeDocQuery(context); + context.endBool(); } @Override diff --git a/src/main/java/com/avaje/ebeaninternal/server/expression/NoopExpression.java b/src/main/java/com/avaje/ebeaninternal/server/expression/NoopExpression.java index 1f833feb6..1c9bc39fa 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/expression/NoopExpression.java +++ b/src/main/java/com/avaje/ebeaninternal/server/expression/NoopExpression.java @@ -23,7 +23,7 @@ class NoopExpression implements SpiExpression { } @Override - public void writeElastic(ElasticExpressionContext context) throws IOException { + public void writeDocQuery(DocQueryContext context) throws IOException { } @Override diff --git a/src/main/java/com/avaje/ebeaninternal/server/expression/NotExpression.java b/src/main/java/com/avaje/ebeaninternal/server/expression/NotExpression.java index 60c3dfb82..be503ab97 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/expression/NotExpression.java +++ b/src/main/java/com/avaje/ebeaninternal/server/expression/NotExpression.java @@ -25,10 +25,10 @@ final class NotExpression implements SpiExpression { } @Override - public void writeElastic(ElasticExpressionContext context) throws IOException { - context.writeBoolMustNotStart(); - exp.writeElastic(context); - context.writeBoolEnd(); + public void writeDocQuery(DocQueryContext context) throws IOException { + context.startBoolMustNot(); + exp.writeDocQuery(context); + context.endBool(); } @Override diff --git a/src/main/java/com/avaje/ebeaninternal/server/expression/NullExpression.java b/src/main/java/com/avaje/ebeaninternal/server/expression/NullExpression.java index 06b55ca50..8035ef881 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/expression/NullExpression.java +++ b/src/main/java/com/avaje/ebeaninternal/server/expression/NullExpression.java @@ -23,7 +23,7 @@ class NullExpression extends AbstractExpression { } @Override - public void writeElastic(ElasticExpressionContext context) throws IOException { + public void writeDocQuery(DocQueryContext context) throws IOException { context.writeExists(notNull, propName); } diff --git a/src/main/java/com/avaje/ebeaninternal/server/expression/RawExpression.java b/src/main/java/com/avaje/ebeaninternal/server/expression/RawExpression.java index 6d4e0c27a..bc381ee59 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/expression/RawExpression.java +++ b/src/main/java/com/avaje/ebeaninternal/server/expression/RawExpression.java @@ -23,8 +23,8 @@ class RawExpression extends NonPrepareExpression { } @Override - public void writeElastic(ElasticExpressionContext context) throws IOException { - context.writeRaw(sql); + public void writeDocQuery(DocQueryContext context) throws IOException { + context.writeRaw(sql, values); } @Override diff --git a/src/main/java/com/avaje/ebeaninternal/server/expression/SimpleExpression.java b/src/main/java/com/avaje/ebeaninternal/server/expression/SimpleExpression.java index 1093c4387..ae771a497 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/expression/SimpleExpression.java +++ b/src/main/java/com/avaje/ebeaninternal/server/expression/SimpleExpression.java @@ -23,12 +23,10 @@ public class SimpleExpression extends AbstractExpression { } @Override - public void writeElastic(ElasticExpressionContext context) throws IOException { - + public void writeDocQuery(DocQueryContext context) throws IOException { if (type == Op.BETWEEN) { throw new IllegalStateException("BETWEEN Not expected in SimpleExpression?"); } - context.writeSimple(type, propName, value); } diff --git a/src/main/java/com/avaje/ebeaninternal/server/querydefn/DefaultOrmQuery.java b/src/main/java/com/avaje/ebeaninternal/server/querydefn/DefaultOrmQuery.java index 5315cadcc..16c196532 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/querydefn/DefaultOrmQuery.java +++ b/src/main/java/com/avaje/ebeaninternal/server/querydefn/DefaultOrmQuery.java @@ -10,8 +10,6 @@ import com.avaje.ebean.bean.PersistenceContext; import com.avaje.ebean.event.BeanQueryRequest; import com.avaje.ebean.event.readaudit.ReadEvent; import com.avaje.ebean.plugin.BeanType; -import com.avaje.ebean.FetchPath; -import com.avaje.ebean.text.json.JsonContext; import com.avaje.ebeaninternal.api.BindParams; import com.avaje.ebeaninternal.api.CQueryPlanKey; import com.avaje.ebeaninternal.api.HashQuery; @@ -27,15 +25,11 @@ import com.avaje.ebeaninternal.server.deploy.BeanPropertyAssocMany; import com.avaje.ebeaninternal.server.deploy.DRawSqlSelect; import com.avaje.ebeaninternal.server.deploy.DeployNamedQuery; import com.avaje.ebeaninternal.server.deploy.TableJoin; -import com.avaje.ebeaninternal.server.expression.ElasticExpressionContext; +import com.avaje.ebeaninternal.server.expression.DefaultExpressionList; import com.avaje.ebeaninternal.server.expression.SimpleExpression; import com.avaje.ebeaninternal.server.query.CancelableQuery; -import com.avaje.ebeaninternal.server.expression.DefaultExpressionList; -import com.fasterxml.jackson.core.JsonGenerator; import javax.persistence.PersistenceException; -import java.io.IOException; -import java.io.StringWriter; import java.sql.Timestamp; import java.util.ArrayList; import java.util.Iterator; @@ -290,64 +284,6 @@ public class DefaultOrmQuery implements SpiQuery { } } - public String asElasticQuery() { - - JsonContext json = server.json(); - - - ElasticExpressionContext context = new ElasticExpressionContext(json, beanDescriptor); - - try { - writeElastic(context); - generatedSql = context.flush(); - return generatedSql; - - } catch (IOException e) { - throw new PersistenceIOException(e); - } - } - - public void writeElastic(ElasticExpressionContext context) throws IOException { - - JsonGenerator json = context.json(); - json.writeStartObject(); - if (firstRow > 0) { - json.writeNumberField("from", firstRow); - } - if (maxRows > 0) { - json.writeNumberField("size", maxRows); - } - - detail.writeElastic(context); - context.writeOrderBy(orderBy); - - json.writeFieldName("query"); - json.writeStartObject(); - - SpiExpression idEquals = null; - if (id != null) { - idEquals = (SpiExpression)expressionFactory.idEq(id); - } - - boolean hasWhere = (whereExpressions != null && !whereExpressions.isEmpty()); - if (idEquals != null || hasWhere) { - json.writeFieldName("filtered"); - json.writeStartObject(); - json.writeFieldName("filter"); - if (hasWhere) { - whereExpressions.writeElastic(context, idEquals); - } else { - idEquals.writeElastic(context); - } - json.writeEndObject(); - } else { - json.writeObjectFieldStart("match_all"); - json.writeEndObject(); - } - json.writeEndObject(); - json.writeEndObject(); - } - @Override public BeanDescriptor getBeanDescriptor() { return beanDescriptor; diff --git a/src/main/java/com/avaje/ebeaninternal/server/querydefn/OrmQueryDetail.java b/src/main/java/com/avaje/ebeaninternal/server/querydefn/OrmQueryDetail.java index 36a331012..9bb6cb081 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/querydefn/OrmQueryDetail.java +++ b/src/main/java/com/avaje/ebeaninternal/server/querydefn/OrmQueryDetail.java @@ -6,12 +6,9 @@ import com.avaje.ebeaninternal.server.deploy.BeanDescriptor; import com.avaje.ebeaninternal.server.deploy.BeanPropertyAssoc; import com.avaje.ebeaninternal.server.el.ElPropertyDeploy; import com.avaje.ebeaninternal.server.el.ElPropertyValue; -import com.avaje.ebeaninternal.server.expression.ElasticExpressionContext; import com.avaje.ebeaninternal.server.query.SplitName; -import com.fasterxml.jackson.core.JsonGenerator; import javax.persistence.PersistenceException; -import java.io.IOException; import java.io.Serializable; import java.util.ArrayList; import java.util.Collections; @@ -440,7 +437,7 @@ public class OrmQueryDetail implements Serializable { } public boolean hasSelectClause() { - return (baseProps.hasSelectClause()); + return baseProps.hasSelectClause(); } /** @@ -503,65 +500,9 @@ public class OrmQueryDetail implements Serializable { } /** - * Write the Elastic search source include and fields if necessary. - *

- * Fetch all property is put into includes. - * Fetch on 'many' path is put into includes. - * Fetch on 'one' paths and root path are put into fields. - *

+ * Return the underlying fetch path entries. */ - public void writeElastic(ElasticExpressionContext context) throws IOException { - - Set includes = new LinkedHashSet(); - Set fields = new LinkedHashSet(); - - for (Map.Entry entry : fetchPaths.entrySet()) { - - String path = entry.getKey(); - OrmQueryProperties value = entry.getValue(); - if (value.allProperties()) { - includes.add(path + ".*"); - } else if (context.containsMany(path)) { - for (String propName : value.getIncluded()) { - includes.add(path + "." + propName); - } - } else { - for (String propName : value.getIncluded()) { - fields.add(path + "." + propName); - } - } - } - - if (hasSelectClause()) { - Set included = baseProps.getIncluded(); - if (included != null) { - for (String propName : included) { - fields.add(propName); - } - } - } - - if (!includes.isEmpty()) { - JsonGenerator json = context.json(); - json.writeFieldName("_source"); - json.writeStartObject(); - json.writeFieldName("include"); - json.writeStartArray(); - for (String propName : includes) { - json.writeString(propName); - } - json.writeEndArray(); - json.writeEndObject(); - } - - if (!fields.isEmpty()) { - JsonGenerator json = context.json(); - json.writeFieldName("fields"); - json.writeStartArray(); - for (String propName : fields) { - json.writeString(propName); - } - json.writeEndArray(); - } + public Set> entries() { + return fetchPaths.entrySet(); } } diff --git a/src/main/java/com/avaje/ebeaninternal/server/querydefn/OrmQueryProperties.java b/src/main/java/com/avaje/ebeaninternal/server/querydefn/OrmQueryProperties.java index f6fcf960f..e3b7a0dca 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/querydefn/OrmQueryProperties.java +++ b/src/main/java/com/avaje/ebeaninternal/server/querydefn/OrmQueryProperties.java @@ -373,7 +373,7 @@ public class OrmQueryProperties implements Serializable { /** * Return the property set. */ - protected Set getIncluded() { + public Set getIncluded() { return included; } diff --git a/src/test/java/com/avaje/ebeaninternal/server/expression/BaseElasticTest.java b/src/test/java/com/avaje/ebeaninternal/server/expression/BaseElasticTest.java deleted file mode 100644 index 1fa13b553..000000000 --- a/src/test/java/com/avaje/ebeaninternal/server/expression/BaseElasticTest.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.avaje.ebeaninternal.server.expression; - - -import com.avaje.ebean.BaseTestCase; -import com.avaje.ebean.Ebean; -import com.avaje.ebeaninternal.server.deploy.BeanDescriptor; -import com.avaje.tests.model.basic.Order; - -import java.io.IOException; - -public abstract class BaseElasticTest extends BaseTestCase { - - public ElasticExpressionContext context() throws IOException { - - BeanDescriptor desc = getBeanDescriptor(Order.class); - return new ElasticExpressionContext(Ebean.json(), desc); - } - -} \ No newline at end of file diff --git a/src/test/java/com/avaje/ebeaninternal/server/expression/SimpleExpressionElasticTest.java b/src/test/java/com/avaje/ebeaninternal/server/expression/SimpleExpressionElasticTest.java deleted file mode 100644 index df02bf88f..000000000 --- a/src/test/java/com/avaje/ebeaninternal/server/expression/SimpleExpressionElasticTest.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.avaje.ebeaninternal.server.expression; - - -import org.junit.Test; - -import static org.assertj.core.api.Assertions.assertThat; - -public class SimpleExpressionElasticTest extends BaseElasticTest { - - @Test - public void writeElastic() throws Exception { - - SimpleExpression eqExp = new SimpleExpression("name", Op.EQ, "rob"); - - ElasticExpressionContext context = context(); - eqExp.writeElastic(context); - - String json = context.flush(); - - assertThat(json).isEqualTo("{\"term\":{\"name\":\"rob\"}}"); - } -} \ No newline at end of file diff --git a/src/test/java/com/avaje/ebeaninternal/server/querydefn/DefaultOrmQueryElasticTest.java b/src/test/java/com/avaje/ebeaninternal/server/querydefn/DefaultOrmQueryElasticTest.java deleted file mode 100644 index bf95d0562..000000000 --- a/src/test/java/com/avaje/ebeaninternal/server/querydefn/DefaultOrmQueryElasticTest.java +++ /dev/null @@ -1,82 +0,0 @@ -package com.avaje.ebeaninternal.server.querydefn; - -import com.avaje.ebean.Ebean; -import com.avaje.ebean.Query; -import com.avaje.ebeaninternal.api.SpiExpressionList; -import com.avaje.ebeaninternal.api.SpiQuery; -import com.avaje.ebeaninternal.server.expression.BaseElasticTest; -import com.avaje.ebeaninternal.server.expression.ElasticExpressionContext; -import com.avaje.tests.model.basic.Order; -import com.fasterxml.jackson.core.JsonGenerator; -import org.junit.Test; - -import java.io.IOException; - -import static org.assertj.core.api.Assertions.assertThat; - -public class DefaultOrmQueryElasticTest extends BaseElasticTest { - - @Test - public void writeElastic_on_SpiExpressionList() throws IOException { - - Query query = Ebean.find(Order.class) - .where().eq("customer.name", "Rob") - .query(); - - SpiQuery spiQuery = (SpiQuery)query; - - SpiExpressionList whereExpressions = spiQuery.getWhereExpressions(); - - ElasticExpressionContext context = context(); - JsonGenerator json = context.json(); - json.writeStartObject(); - json.writeFieldName("filter"); - - whereExpressions.writeElastic(context); - - json.writeEndObject(); - - assertThat(context.flush()).isEqualTo("{\"filter\":{\"term\":{\"customer.name\":\"Rob\"}}}"); - } - - @Test - public void writeElastic() throws IOException { - - Query query = Ebean.find(Order.class) - .select("status, customer.name, details.product.id") - .where().eq("customer.name", "Rob") - .query(); - - SpiQuery spiQuery = (SpiQuery)query; - - ElasticExpressionContext context = context(); - spiQuery.writeElastic(context); - - assertThat(context.flush()).isEqualTo("{\"fields\":[\"status\",\"customer.name\",\"details.product.id\"],\"query\":{\"filtered\":{\"filter\":{\"term\":{\"customer.name\":\"Rob\"}}}}}"); - } - - @Test - public void asElasticQuery() throws IOException { - - String elasticQuery = Ebean.find(Order.class) - .select("status") - .where().eq("customer.name", "Rob") - .query().asElasticQuery(); - - - assertThat(elasticQuery).isEqualTo("{\"fields\":[\"status\"],\"query\":{\"filtered\":{\"filter\":{\"term\":{\"customer.name\":\"Rob\"}}}}}"); - } - - @Test - public void asElasticQuery_firstRowsMaxRows() throws IOException { - - String elasticQuery = Ebean.find(Order.class) - .select("status") - .setFirstRow(3) - .setMaxRows(100) - .where().eq("customer.name", "Rob") - .query().asElasticQuery(); - - assertThat(elasticQuery).isEqualTo("{\"from\":3,\"size\":100,\"fields\":[\"status\"],\"query\":{\"filtered\":{\"filter\":{\"term\":{\"customer.name\":\"Rob\"}}}}}"); - } -} \ No newline at end of file