mirror of
https://github.com/ebean-orm/ebean.git
synced 2026-10-25 15:58:40 +00:00
#589 - ElasticSearch - refactor to DocQueryContext
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
+3
-4
@@ -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
|
||||
|
||||
+2
-2
@@ -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
|
||||
|
||||
+4
-4
@@ -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;
|
||||
}
|
||||
-430
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user