#589 - ElasticSearch - refactor to DocQueryContext

This commit is contained in:
Robin Bygrave
2016-03-08 00:00:02 +13:00
parent da8766533f
commit 37b86f2191
32 changed files with 155 additions and 788 deletions
-5
View File
@@ -1373,9 +1373,4 @@ public interface Query<T> {
*/
Set<String> validate();
/**
* Return the query in JSON form for ElasticSearch doc store.
*/
String asElasticQuery();
}
@@ -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.
@@ -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<T> extends ExpressionList<T>, SpiExpression {
*/
boolean isEmpty();
/**
* Write the top level where expressions taking into account possible extra idEquals expression.
*/
void writeDocQuery(DocQueryContext context, SpiExpression idEquals) throws IOException;
}
@@ -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<T> extends Query<T> {
}
}
/**
* Write the query as an elastic search query.
*/
void writeElastic(ElasticExpressionContext context) throws IOException;
/**
* Return true if AutoTune should be attempted on this query.
*/
@@ -28,19 +28,8 @@ class AllEqualsExpression extends NonPrepareExpression {
}
@Override
public void writeElastic(ElasticExpressionContext context) throws IOException {
context.writeBoolMustStart();
for (Map.Entry<String, Object> 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
@@ -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);
}
@@ -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
@@ -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
@@ -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();
}
}
@@ -61,29 +61,29 @@ public class DefaultExpressionList<T> implements SpiExpressionList<T> {
}
@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();
}
}
@@ -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<String, Object> propMap) throws IOException;
/**
* Write a Like expression.
*/
void writeLike(String propName, String val, LikeType type, boolean caseInsensitive) throws IOException;
}
@@ -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.
* <p>
* 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<Object> ids = new ArrayList<Object>(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 <T> void writeOrderBy(OrderBy<T> 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();
}
}
}
@@ -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");
}
@@ -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);
}
@@ -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);
}
@@ -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
@@ -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");
}
@@ -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);
@@ -100,14 +100,13 @@ abstract class JunctionExpression<T> implements Junction<T>, SpiExpression, Expr
}
@Override
public void writeElastic(ElasticExpressionContext context) throws IOException {
context.writeBoolStart(!disjunction);
public void writeDocQuery(DocQueryContext context) throws IOException {
context.startBool(!disjunction);
List<SpiExpression> 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
@@ -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
@@ -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
@@ -23,7 +23,7 @@ class NoopExpression implements SpiExpression {
}
@Override
public void writeElastic(ElasticExpressionContext context) throws IOException {
public void writeDocQuery(DocQueryContext context) throws IOException {
}
@Override
@@ -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
@@ -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);
}
@@ -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
@@ -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);
}
@@ -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<T> implements SpiQuery<T> {
}
}
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<T> getBeanDescriptor() {
return beanDescriptor;
@@ -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.
* <p>
* 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.
* </p>
* Return the underlying fetch path entries.
*/
public void writeElastic(ElasticExpressionContext context) throws IOException {
Set<String> includes = new LinkedHashSet<String>();
Set<String> fields = new LinkedHashSet<String>();
for (Map.Entry<String, OrmQueryProperties> 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<String> 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<Map.Entry<String, OrmQueryProperties>> entries() {
return fetchPaths.entrySet();
}
}
@@ -373,7 +373,7 @@ public class OrmQueryProperties implements Serializable {
/**
* Return the property set.
*/
protected Set<String> getIncluded() {
public Set<String> getIncluded() {
return included;
}