mirror of
https://github.com/ebean-orm/ebean.git
synced 2026-10-24 15:55:55 +00:00
#594 ElasticSearch - Add match / TextExpression support - move expressions onto ExpressionList (remove TextExpressionList)
This commit is contained in:
@@ -357,6 +357,6 @@ public interface ExpressionFactory {
|
||||
* This is doc store Elastic only.
|
||||
* </p>
|
||||
*/
|
||||
<T> TextJunction<T> textJunction(Query<T> query, TextExpressionList<T> parent, TextJunction.Type type);
|
||||
<T> Junction<T> textJunction(Query<T> query, ExpressionList<T> parent, Junction.Type type);
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
package com.avaje.ebean;
|
||||
|
||||
import com.avaje.ebean.search.Match;
|
||||
import com.avaje.ebean.search.MultiMatch;
|
||||
import com.avaje.ebean.search.TextCommonTerms;
|
||||
import com.avaje.ebean.search.TextQueryString;
|
||||
import com.avaje.ebean.search.TextSimple;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.persistence.NonUniqueResultException;
|
||||
@@ -842,6 +847,47 @@ public interface ExpressionList<T> {
|
||||
*/
|
||||
ExpressionList<T> not(Expression exp);
|
||||
|
||||
/**
|
||||
* Add a match expression.
|
||||
*
|
||||
* @param propertyName The property name for the match
|
||||
* @param search The search value
|
||||
*/
|
||||
ExpressionList<T> match(String propertyName, String search);
|
||||
|
||||
/**
|
||||
* Add a match expression with options.
|
||||
*
|
||||
* @param propertyName The property name for the match
|
||||
* @param search The search value
|
||||
*/
|
||||
ExpressionList<T> match(String propertyName, String search, Match options);
|
||||
|
||||
/**
|
||||
* Add a multi-match expression.
|
||||
*/
|
||||
ExpressionList<T> multiMatch(String search, String... properties);
|
||||
|
||||
/**
|
||||
* Add a multi-match expression using options.
|
||||
*/
|
||||
ExpressionList<T> multiMatch(String search, MultiMatch options);
|
||||
|
||||
/**
|
||||
* Add a simple query string expression.
|
||||
*/
|
||||
ExpressionList<T> textSimple(String search, TextSimple options);
|
||||
|
||||
/**
|
||||
* Add a query string expression.
|
||||
*/
|
||||
ExpressionList<T> textQueryString(String search, TextQueryString options);
|
||||
|
||||
/**
|
||||
* Add common terms expression.
|
||||
*/
|
||||
ExpressionList<T> textCommonTerms(String search, TextCommonTerms options);
|
||||
|
||||
/**
|
||||
* Return a list of expressions that will be joined by AND's.
|
||||
*/
|
||||
@@ -861,4 +907,33 @@ public interface ExpressionList<T> {
|
||||
*/
|
||||
ExpressionList<T> endJunction();
|
||||
|
||||
/**
|
||||
* Start a list of expressions that will be joined by MUST.
|
||||
*/
|
||||
Junction<T> must();
|
||||
|
||||
/**
|
||||
* Start a list of expressions that will be joined by SHOULD.
|
||||
*/
|
||||
Junction<T> should();
|
||||
|
||||
/**
|
||||
* Start a list of expressions that will be joined by MUST NOT.
|
||||
*/
|
||||
Junction<T> mustNot();
|
||||
|
||||
/**
|
||||
* End the list of MUST expressions.
|
||||
*/
|
||||
ExpressionList<T> endMust();
|
||||
|
||||
/**
|
||||
* End the list of SHOULD expressions.
|
||||
*/
|
||||
ExpressionList<T> endShould();
|
||||
|
||||
/**
|
||||
* End the list of MUST NOT expressions.
|
||||
*/
|
||||
ExpressionList<T> endMustNot();
|
||||
}
|
||||
|
||||
@@ -9,25 +9,25 @@ package com.avaje.ebean;
|
||||
* <p>
|
||||
* Note: where() always takes you to the top level WHERE expression list.
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
* <pre class="code">
|
||||
* Query q =
|
||||
* Ebean.find(Person.class)
|
||||
* .where().disjunction()
|
||||
* .like("name", "Rob%")
|
||||
* .eq("status", Status.NEW)
|
||||
*
|
||||
*
|
||||
* // where() returns us to the top level expression list
|
||||
* .where().gt("id", 10);
|
||||
*
|
||||
*
|
||||
* // read as...
|
||||
* // where ( ((name like Rob%) or (status = NEW)) AND (id > 10) )
|
||||
* </pre>
|
||||
*
|
||||
*
|
||||
* <p>
|
||||
* Note: endJunction() takes you to the parent expression list
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
* <pre class="code">
|
||||
* Query q =
|
||||
* Ebean.find(Person.class)
|
||||
@@ -35,22 +35,22 @@ package com.avaje.ebean;
|
||||
* .like("name", "Rob%")
|
||||
* .eq("status", Status.NEW)
|
||||
* .endJunction()
|
||||
*
|
||||
*
|
||||
* // endJunction().. takes us to the 'parent' expression list
|
||||
* // which in this case is the top level (same as where())
|
||||
*
|
||||
*
|
||||
* .gt("id", 10);
|
||||
*
|
||||
*
|
||||
* // read as...
|
||||
* // where ( ((name like Rob%) or (status = NEW)) AND (id > 10) )
|
||||
* </pre>
|
||||
*
|
||||
*
|
||||
* <p>
|
||||
* Example of a nested disjunction.
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
* <pre class="code">
|
||||
* Query<Customer> q =
|
||||
* Query<Customer> q =
|
||||
* Ebean.find(Customer.class)
|
||||
* .where()
|
||||
* .disjunction()
|
||||
@@ -63,16 +63,60 @@ package com.avaje.ebean;
|
||||
* .gt("id", 0)
|
||||
* .endJunction()
|
||||
* .order().asc("name");
|
||||
*
|
||||
*
|
||||
* q.findList();
|
||||
* String s = q.getGeneratedSql();
|
||||
*
|
||||
*
|
||||
* // this produces an expression like:
|
||||
*
|
||||
*
|
||||
* ( name like ? and c.anniversary = ? ) or (c.status = ? and c.id > ? )
|
||||
*
|
||||
*
|
||||
* </pre>
|
||||
*/
|
||||
public interface Junction<T> extends Expression, ExpressionList<T> {
|
||||
|
||||
/**
|
||||
* The type of Junction used in full text expressions.
|
||||
*/
|
||||
enum Type {
|
||||
|
||||
/**
|
||||
* AND group.
|
||||
*/
|
||||
AND(" and "),
|
||||
|
||||
/**
|
||||
* OR group.
|
||||
*/
|
||||
OR(" or "),
|
||||
|
||||
/**
|
||||
* Text search AND group.
|
||||
*/
|
||||
MUST("must"),
|
||||
|
||||
/**
|
||||
* Text search NOT group.
|
||||
*/
|
||||
MUST_NOT("must_not"),
|
||||
|
||||
/**
|
||||
* Text search OR group.
|
||||
*/
|
||||
SHOULD("should");
|
||||
|
||||
String literal;
|
||||
|
||||
Type(String literal) {
|
||||
this.literal = literal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the literal value for this type.
|
||||
*/
|
||||
public String literal() {
|
||||
return literal;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1060,7 +1060,7 @@ public interface Query<T> {
|
||||
* ElasticSearch query.
|
||||
* </p>
|
||||
*/
|
||||
TextExpressionList<T> text();
|
||||
ExpressionList<T> text();
|
||||
|
||||
/**
|
||||
* This applies a filter on the 'many' property list rather than the root
|
||||
|
||||
@@ -1,88 +0,0 @@
|
||||
package com.avaje.ebean;
|
||||
|
||||
import com.avaje.ebean.search.Match;
|
||||
import com.avaje.ebean.search.MultiMatch;
|
||||
import com.avaje.ebean.search.TextCommonTerms;
|
||||
import com.avaje.ebean.search.TextQueryString;
|
||||
import com.avaje.ebean.search.TextSimple;
|
||||
|
||||
/**
|
||||
* An list of Full text query expressions.
|
||||
* <p>
|
||||
* For ElasticSearch these expression go into the "query" section rather than the "filter" section.
|
||||
* </p>
|
||||
*/
|
||||
public interface TextExpressionList<T> extends ExpressionList<T> {
|
||||
|
||||
/**
|
||||
* Add a match expression.
|
||||
*
|
||||
* @param propertyName The property name for the match
|
||||
* @param search The search value
|
||||
*/
|
||||
TextExpressionList<T> match(String propertyName, String search);
|
||||
|
||||
/**
|
||||
* Add a match expression with options.
|
||||
*
|
||||
* @param propertyName The property name for the match
|
||||
* @param search The search value
|
||||
*/
|
||||
TextExpressionList<T> match(String propertyName, String search, Match options);
|
||||
|
||||
/**
|
||||
* Add a multi-match expression.
|
||||
*/
|
||||
TextExpressionList<T> multiMatch(String search, String... properties);
|
||||
|
||||
/**
|
||||
* Add a multi-match expression using options.
|
||||
*/
|
||||
TextExpressionList<T> multiMatch(String search, MultiMatch options);
|
||||
|
||||
/**
|
||||
* Add a simple query string expression.
|
||||
*/
|
||||
TextExpressionList<T> textSimple(String search, TextSimple options);
|
||||
|
||||
/**
|
||||
* Add a query string expression.
|
||||
*/
|
||||
TextExpressionList<T> textQueryString(String search, TextQueryString options);
|
||||
|
||||
/**
|
||||
* Add common terms expression.
|
||||
*/
|
||||
TextExpressionList<T> textCommonTerms(String search, TextCommonTerms options);
|
||||
|
||||
/**
|
||||
* Start a list of expressions that will be joined by MUST.
|
||||
*/
|
||||
TextJunction<T> must();
|
||||
|
||||
/**
|
||||
* Start a list of expressions that will be joined by SHOULD.
|
||||
*/
|
||||
TextJunction<T> should();
|
||||
|
||||
/**
|
||||
* Start a list of expressions that will be joined by MUST NOT.
|
||||
*/
|
||||
TextJunction<T> mustNot();
|
||||
|
||||
/**
|
||||
* End the list of MUST expressions.
|
||||
*/
|
||||
TextExpressionList<T> endMust();
|
||||
|
||||
/**
|
||||
* End the list of SHOULD expressions.
|
||||
*/
|
||||
TextExpressionList<T> endShould();
|
||||
|
||||
/**
|
||||
* End the list of MUST NOT expressions.
|
||||
*/
|
||||
TextExpressionList<T> endMustNot();
|
||||
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
package com.avaje.ebean;
|
||||
|
||||
/**
|
||||
* A Full text MUST, MUST NOT or SHOULD group of expressions.
|
||||
*/
|
||||
public interface TextJunction<T> extends Junction<T>, TextExpressionList<T> {
|
||||
|
||||
/**
|
||||
* The type of Junction used in full text expressions.
|
||||
*/
|
||||
enum Type {
|
||||
|
||||
/**
|
||||
* Logically a AND group.
|
||||
*/
|
||||
MUST("must"),
|
||||
|
||||
/**
|
||||
* Logically a NOT group.
|
||||
*/
|
||||
MUST_NOT("must_not"),
|
||||
|
||||
/**
|
||||
* Logically a OR group.
|
||||
*/
|
||||
SHOULD("should");
|
||||
|
||||
String literal;
|
||||
|
||||
Type(String literal) {
|
||||
this.literal = literal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the literal value for this type.
|
||||
*/
|
||||
public String literal() {
|
||||
return literal;
|
||||
}
|
||||
}
|
||||
}
|
||||
+4
-5
@@ -1,18 +1,17 @@
|
||||
package com.avaje.ebeaninternal.api;
|
||||
|
||||
import com.avaje.ebean.TextJunction;
|
||||
import com.avaje.ebean.Junction;
|
||||
import com.avaje.ebeaninternal.server.expression.DocQueryContext;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* SPI extension to the full text junctions (MUST, MUST NOT, SHOULD).
|
||||
* SPI methods for Junction.
|
||||
*/
|
||||
public interface SpiTextJunction<T> extends TextJunction<T> {
|
||||
public interface SpiJunction<T> extends Junction<T> {
|
||||
|
||||
/**
|
||||
* Write the junction expression to the query context.
|
||||
* Write the Junction taking into account it is implied.
|
||||
*/
|
||||
void writeDocQueryJunction(DocQueryContext context) throws IOException;
|
||||
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
package com.avaje.ebeaninternal.api;
|
||||
|
||||
import com.avaje.ebean.TextExpressionList;
|
||||
|
||||
/**
|
||||
* SPI extensions to Full text expression list.
|
||||
*/
|
||||
public interface SpiTextExpressionList<T> extends TextExpressionList<T> {
|
||||
|
||||
}
|
||||
@@ -18,31 +18,33 @@ public abstract class AbstractTextExpression extends AbstractExpression {
|
||||
|
||||
@Override
|
||||
public void addSql(SpiExpressionRequest request) {
|
||||
throw new IllegalStateException("Not implemented - DocStore/Elastic only");
|
||||
// do nothing, only execute against document store
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addBindValues(SpiExpressionRequest request) {
|
||||
throw new IllegalStateException("Not implemented - DocStore/Elastic only");
|
||||
// do nothing, only execute against document store
|
||||
}
|
||||
|
||||
@Override
|
||||
public void queryPlanHash(HashQueryPlanBuilder builder) {
|
||||
throw new IllegalStateException("Not implemented - query plan caching done explicitly by the doc store");
|
||||
// do nothing, only execute against document store
|
||||
}
|
||||
|
||||
@Override
|
||||
public int queryBindHash() {
|
||||
throw new IllegalStateException("Not implemented - query plan caching done explicitly by the doc store");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSameByPlan(SpiExpression other) {
|
||||
throw new IllegalStateException("Not implemented - query plan caching done explicitly by the doc store");
|
||||
// do not compare by plan / bind values (this way)
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSameByBind(SpiExpression other) {
|
||||
throw new IllegalStateException("Not implemented - query plan caching done explicitly by the doc store");
|
||||
// do not compare by plan / bind values (this way)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,113 +0,0 @@
|
||||
package com.avaje.ebeaninternal.server.expression;
|
||||
|
||||
import com.avaje.ebean.Query;
|
||||
import com.avaje.ebean.TextExpressionList;
|
||||
import com.avaje.ebean.TextJunction;
|
||||
import com.avaje.ebean.search.Match;
|
||||
import com.avaje.ebean.search.MultiMatch;
|
||||
import com.avaje.ebean.search.TextCommonTerms;
|
||||
import com.avaje.ebean.search.TextQueryString;
|
||||
import com.avaje.ebean.search.TextSimple;
|
||||
import com.avaje.ebeaninternal.api.SpiExpression;
|
||||
import com.avaje.ebeaninternal.api.SpiTextJunction;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Implementation of SpiTextJunction (Must, Must Not or Should group).
|
||||
*/
|
||||
class DTextJunction<T> extends JunctionExpression<T> implements SpiTextJunction<T> {
|
||||
|
||||
private final TextJunction.Type type;
|
||||
|
||||
DTextJunction(Query<T> query, TextExpressionList<T> parent, TextJunction.Type type) {
|
||||
super(query, parent);
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeDocQueryJunction(DocQueryContext context) throws IOException {
|
||||
context.startBoolGroupList(type);
|
||||
List<SpiExpression> list = exprList.internalList();
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
list.get(i).writeDocQuery(context);
|
||||
}
|
||||
context.endBoolGroupList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpiExpression copyForPlanKey() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextExpressionList<T> match(String propertyName, String search) {
|
||||
return match(propertyName, search, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextExpressionList<T> match(String propertyName, String search, Match options) {
|
||||
return exprList.match(propertyName, search, options);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextExpressionList<T> multiMatch(String query, String... properties) {
|
||||
return exprList.multiMatch(query, properties);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextExpressionList<T> multiMatch(String query, MultiMatch options) {
|
||||
return exprList.multiMatch(query, options);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextExpressionList<T> textSimple(String search, TextSimple options) {
|
||||
return exprList.textSimple(search, options);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextExpressionList<T> textQueryString(String search, TextQueryString options) {
|
||||
return exprList.textQueryString(search, options);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextExpressionList<T> textCommonTerms(String search, TextCommonTerms options) {
|
||||
return exprList.textCommonTerms(search, options);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextJunction<T> must() {
|
||||
return exprList.must();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextJunction<T> should() {
|
||||
return exprList.should();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextJunction<T> mustNot() {
|
||||
return exprList.mustNot();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextExpressionList<T> endMust() {
|
||||
return endTextJunction();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextExpressionList<T> endShould() {
|
||||
return endTextJunction();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextExpressionList<T> endMustNot() {
|
||||
return endTextJunction();
|
||||
}
|
||||
|
||||
private TextExpressionList<T> endTextJunction() {
|
||||
return exprList.endTextJunction();
|
||||
}
|
||||
|
||||
}
|
||||
+2
-8
@@ -7,8 +7,6 @@ import com.avaje.ebean.ExpressionList;
|
||||
import com.avaje.ebean.Junction;
|
||||
import com.avaje.ebean.LikeType;
|
||||
import com.avaje.ebean.Query;
|
||||
import com.avaje.ebean.TextExpressionList;
|
||||
import com.avaje.ebean.TextJunction;
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
import com.avaje.ebean.search.Match;
|
||||
import com.avaje.ebean.search.MultiMatch;
|
||||
@@ -438,7 +436,6 @@ public class DefaultExpressionFactory implements SpiExpressionFactory {
|
||||
* Return a list of expressions that will be joined by AND's.
|
||||
*/
|
||||
public <T> Junction<T> conjunction(Query<T> query) {
|
||||
|
||||
return new JunctionExpression.Conjunction<T>(query, query.where());
|
||||
}
|
||||
|
||||
@@ -446,7 +443,6 @@ public class DefaultExpressionFactory implements SpiExpressionFactory {
|
||||
* Return a list of expressions that will be joined by OR's.
|
||||
*/
|
||||
public <T> Junction<T> disjunction(Query<T> query) {
|
||||
|
||||
return new JunctionExpression.Disjunction<T>(query, query.where());
|
||||
}
|
||||
|
||||
@@ -454,7 +450,6 @@ public class DefaultExpressionFactory implements SpiExpressionFactory {
|
||||
* Return a list of expressions that will be joined by AND's.
|
||||
*/
|
||||
public <T> Junction<T> conjunction(Query<T> query, ExpressionList<T> parent) {
|
||||
|
||||
return new JunctionExpression.Conjunction<T>(query, parent);
|
||||
}
|
||||
|
||||
@@ -462,7 +457,6 @@ public class DefaultExpressionFactory implements SpiExpressionFactory {
|
||||
* Return a list of expressions that will be joined by OR's.
|
||||
*/
|
||||
public <T> Junction<T> disjunction(Query<T> query, ExpressionList<T> parent) {
|
||||
|
||||
return new JunctionExpression.Disjunction<T>(query, parent);
|
||||
}
|
||||
|
||||
@@ -470,7 +464,7 @@ public class DefaultExpressionFactory implements SpiExpressionFactory {
|
||||
* Create and return a Full text junction (Must, Must Not or Should).
|
||||
*/
|
||||
@Override
|
||||
public <T> TextJunction<T> textJunction(Query<T> query, TextExpressionList<T> parent, TextJunction.Type type) {
|
||||
return new DTextJunction<T>(query, parent, type);
|
||||
public <T> Junction<T> textJunction(Query<T> query, ExpressionList<T> parent, Junction.Type type) {
|
||||
return new JunctionExpression.TextJunction<T>(query, parent, type);
|
||||
}
|
||||
}
|
||||
|
||||
+35
-31
@@ -13,8 +13,7 @@ import com.avaje.ebeaninternal.api.SpiExpression;
|
||||
import com.avaje.ebeaninternal.api.SpiExpressionList;
|
||||
import com.avaje.ebeaninternal.api.SpiExpressionRequest;
|
||||
import com.avaje.ebeaninternal.api.SpiExpressionValidation;
|
||||
import com.avaje.ebeaninternal.api.SpiTextExpressionList;
|
||||
import com.avaje.ebeaninternal.api.SpiTextJunction;
|
||||
import com.avaje.ebeaninternal.api.SpiJunction;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
|
||||
import java.io.IOException;
|
||||
@@ -28,13 +27,13 @@ import java.util.Set;
|
||||
/**
|
||||
* Default implementation of ExpressionList.
|
||||
*/
|
||||
public class DefaultExpressionList<T> implements SpiExpressionList<T>, SpiTextExpressionList<T> {
|
||||
public class DefaultExpressionList<T> implements SpiExpressionList<T> {
|
||||
|
||||
protected final List<SpiExpression> list;
|
||||
|
||||
protected final Query<T> query;
|
||||
|
||||
protected final TextExpressionList<T> parentExprList;
|
||||
protected final ExpressionList<T> parentExprList;
|
||||
|
||||
protected transient ExpressionFactory expr;
|
||||
|
||||
@@ -54,19 +53,19 @@ public class DefaultExpressionList<T> implements SpiExpressionList<T>, SpiTextEx
|
||||
this(query, query.getExpressionFactory(), null, new ArrayList<SpiExpression>(), true);
|
||||
}
|
||||
|
||||
public DefaultExpressionList(Query<T> query, TextExpressionList<T> parentExprList) {
|
||||
public DefaultExpressionList(Query<T> query, ExpressionList<T> parentExprList) {
|
||||
this(query, query.getExpressionFactory(), parentExprList);
|
||||
}
|
||||
|
||||
public DefaultExpressionList(Query<T> query, ExpressionFactory expr, TextExpressionList<T> parentExprList) {
|
||||
public DefaultExpressionList(Query<T> query, ExpressionFactory expr, ExpressionList<T> parentExprList) {
|
||||
this(query, expr, parentExprList, new ArrayList<SpiExpression>());
|
||||
}
|
||||
|
||||
protected DefaultExpressionList(Query<T> query, ExpressionFactory expr, TextExpressionList<T> parentExprList, List<SpiExpression> list) {
|
||||
protected DefaultExpressionList(Query<T> query, ExpressionFactory expr, ExpressionList<T> parentExprList, List<SpiExpression> list) {
|
||||
this(query, expr, parentExprList, list, false);
|
||||
}
|
||||
|
||||
private DefaultExpressionList(Query<T> query, ExpressionFactory expr, TextExpressionList<T> parentExprList, List<SpiExpression> list, boolean textRoot) {
|
||||
private DefaultExpressionList(Query<T> query, ExpressionFactory expr, ExpressionList<T> parentExprList, List<SpiExpression> list, boolean textRoot) {
|
||||
this.textRoot = textRoot;
|
||||
this.list = list;
|
||||
this.query = query;
|
||||
@@ -104,20 +103,20 @@ public class DefaultExpressionList<T> implements SpiExpressionList<T>, SpiTextEx
|
||||
int size = list.size();
|
||||
|
||||
SpiExpression first = list.get(0);
|
||||
boolean explicitBool = first instanceof SpiTextJunction<?>;
|
||||
boolean explicitBool = first instanceof SpiJunction<?>;
|
||||
boolean implicitBool = !explicitBool && size > 1;
|
||||
|
||||
if (implicitBool || explicitBool) {
|
||||
context.startBoolGroup();
|
||||
}
|
||||
if (implicitBool) {
|
||||
context.startBoolGroupList(TextJunction.Type.SHOULD);
|
||||
context.startBoolGroupList(Junction.Type.SHOULD);
|
||||
}
|
||||
for (int i = 0; i < size; i++) {
|
||||
SpiExpression expr = list.get(i);
|
||||
if (explicitBool) {
|
||||
try {
|
||||
((SpiTextJunction<?>) expr).writeDocQueryJunction(context);
|
||||
((SpiJunction<?>)expr).writeDocQueryJunction(context);
|
||||
} catch (ClassCastException e) {
|
||||
throw new IllegalStateException("The top level text() expressions should be all be 'Must', 'Should' or 'Must Not' or none of them should be.", e);
|
||||
}
|
||||
@@ -208,7 +207,7 @@ public class DefaultExpressionList<T> implements SpiExpressionList<T>, SpiTextEx
|
||||
return parentExprList == null ? this : parentExprList;
|
||||
}
|
||||
|
||||
protected TextExpressionList<T> endTextJunction() {
|
||||
protected ExpressionList<T> endTextJunction() {
|
||||
return parentExprList == null ? this : parentExprList;
|
||||
}
|
||||
|
||||
@@ -647,8 +646,8 @@ public class DefaultExpressionList<T> implements SpiExpressionList<T>, SpiTextEx
|
||||
return this;
|
||||
}
|
||||
|
||||
public TextJunction<T> textJunction(TextJunction.Type type) {
|
||||
TextJunction<T> junction = expr.textJunction(query, this, type);
|
||||
public Junction<T> textJunction(Junction.Type type) {
|
||||
Junction<T> junction = expr.textJunction(query, this, type);
|
||||
add(junction);
|
||||
return junction;
|
||||
}
|
||||
@@ -858,72 +857,77 @@ public class DefaultExpressionList<T> implements SpiExpressionList<T>, SpiTextEx
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextExpressionList<T> match(String propertyName, String search) {
|
||||
public ExpressionList<T> match(String propertyName, String search) {
|
||||
return match(propertyName, search, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextExpressionList<T> match(String propertyName, String search, Match options) {
|
||||
public ExpressionList<T> match(String propertyName, String search, Match options) {
|
||||
add(expr.textMatch(propertyName, search, options));
|
||||
setUseDocStore(true);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextExpressionList<T> multiMatch(String query, String... fields) {
|
||||
return multiMatch(query, new MultiMatch().fields(fields));
|
||||
public ExpressionList<T> multiMatch(String query, String... fields) {
|
||||
return multiMatch(query, MultiMatch.fields(fields));
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextExpressionList<T> multiMatch(String query, MultiMatch options) {
|
||||
public ExpressionList<T> multiMatch(String query, MultiMatch options) {
|
||||
setUseDocStore(true);
|
||||
add(expr.textMultiMatch(query, options));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextExpressionList<T> textSimple(String search, TextSimple options) {
|
||||
public ExpressionList<T> textSimple(String search, TextSimple options) {
|
||||
setUseDocStore(true);
|
||||
add(expr.textSimple(search, options));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextExpressionList<T> textQueryString(String search, TextQueryString options) {
|
||||
public ExpressionList<T> textQueryString(String search, TextQueryString options) {
|
||||
setUseDocStore(true);
|
||||
add(expr.textQueryString(search, options));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextExpressionList<T> textCommonTerms(String search, TextCommonTerms options) {
|
||||
public ExpressionList<T> textCommonTerms(String search, TextCommonTerms options) {
|
||||
setUseDocStore(true);
|
||||
add(expr.textCommonTerms(search, options));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextJunction<T> must() {
|
||||
return textJunction(TextJunction.Type.MUST);
|
||||
public Junction<T> must() {
|
||||
return textJunction(Junction.Type.MUST);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextJunction<T> should() {
|
||||
return textJunction(TextJunction.Type.SHOULD);
|
||||
public Junction<T> should() {
|
||||
return textJunction(Junction.Type.SHOULD);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextJunction<T> mustNot() {
|
||||
return textJunction(TextJunction.Type.MUST_NOT);
|
||||
public Junction<T> mustNot() {
|
||||
return textJunction(Junction.Type.MUST_NOT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextExpressionList<T> endMust() {
|
||||
public ExpressionList<T> endMust() {
|
||||
return endTextJunction();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextExpressionList<T> endShould() {
|
||||
public ExpressionList<T> endShould() {
|
||||
return endTextJunction();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextExpressionList<T> endMustNot() {
|
||||
public ExpressionList<T> endMustNot() {
|
||||
return endTextJunction();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.avaje.ebeaninternal.server.expression;
|
||||
|
||||
import com.avaje.ebean.Junction;
|
||||
import com.avaje.ebean.LikeType;
|
||||
import com.avaje.ebean.TextJunction;
|
||||
import com.avaje.ebean.search.Match;
|
||||
import com.avaje.ebean.search.MultiMatch;
|
||||
import com.avaje.ebean.search.TextCommonTerms;
|
||||
@@ -130,7 +130,7 @@ public interface DocQueryContext {
|
||||
/**
|
||||
* Start a Must, Must Not or Should list.
|
||||
*/
|
||||
void startBoolGroupList(TextJunction.Type type) throws IOException;
|
||||
void startBoolGroupList(Junction.Type type) throws IOException;
|
||||
|
||||
/**
|
||||
* End a Must, Must Not or Should list.
|
||||
|
||||
@@ -2,11 +2,17 @@ package com.avaje.ebeaninternal.server.expression;
|
||||
|
||||
import com.avaje.ebean.*;
|
||||
import com.avaje.ebean.event.BeanQueryRequest;
|
||||
import com.avaje.ebean.search.Match;
|
||||
import com.avaje.ebean.search.MultiMatch;
|
||||
import com.avaje.ebean.search.TextCommonTerms;
|
||||
import com.avaje.ebean.search.TextQueryString;
|
||||
import com.avaje.ebean.search.TextSimple;
|
||||
import com.avaje.ebeaninternal.api.HashQueryPlanBuilder;
|
||||
import com.avaje.ebeaninternal.api.ManyWhereJoins;
|
||||
import com.avaje.ebeaninternal.api.SpiExpression;
|
||||
import com.avaje.ebeaninternal.api.SpiExpressionRequest;
|
||||
import com.avaje.ebeaninternal.api.SpiExpressionValidation;
|
||||
import com.avaje.ebeaninternal.api.SpiJunction;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
|
||||
import java.io.IOException;
|
||||
@@ -19,20 +25,30 @@ import java.util.Set;
|
||||
/**
|
||||
* Junction implementation.
|
||||
*/
|
||||
abstract class JunctionExpression<T> implements Junction<T>, SpiExpression, ExpressionList<T> {
|
||||
abstract class JunctionExpression<T> implements SpiJunction<T>, SpiExpression, ExpressionList<T> {
|
||||
|
||||
static final String OR = " or ";
|
||||
static class TextJunction<T> extends JunctionExpression<T> {
|
||||
|
||||
static final String AND = " and ";
|
||||
TextJunction(Query<T> query, ExpressionList<T> parent, TextJunction.Type type) {
|
||||
super(type, query, parent);
|
||||
}
|
||||
TextJunction(TextJunction.Type type, DefaultExpressionList<T> expressionList) {
|
||||
super(type, expressionList);
|
||||
}
|
||||
@Override
|
||||
public SpiExpression copyForPlanKey() {
|
||||
return new TextJunction<T>(type, exprList.copyForPlanKey());
|
||||
}
|
||||
}
|
||||
|
||||
static class Conjunction<T> extends JunctionExpression<T> {
|
||||
|
||||
Conjunction(Query<T> query, ExpressionList<T> parent) {
|
||||
super(false, AND, query, parent);
|
||||
super(Type.AND, query, parent);
|
||||
}
|
||||
|
||||
Conjunction(DefaultExpressionList<T> expressionList) {
|
||||
super(false, AND, expressionList);
|
||||
super(Type.AND, expressionList);
|
||||
}
|
||||
@Override
|
||||
public SpiExpression copyForPlanKey() {
|
||||
@@ -43,11 +59,11 @@ abstract class JunctionExpression<T> implements Junction<T>, SpiExpression, Expr
|
||||
static class Disjunction<T> extends JunctionExpression<T> {
|
||||
|
||||
Disjunction(Query<T> query, ExpressionList<T> parent) {
|
||||
super(true, OR, query, parent);
|
||||
super(Type.OR, query, parent);
|
||||
}
|
||||
|
||||
Disjunction(DefaultExpressionList<T> expressionList) {
|
||||
super(true, OR, expressionList);
|
||||
super(Type.OR, expressionList);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -58,37 +74,24 @@ abstract class JunctionExpression<T> implements Junction<T>, SpiExpression, Expr
|
||||
|
||||
protected final DefaultExpressionList<T> exprList;
|
||||
|
||||
private final String joinType;
|
||||
protected final Junction.Type type;
|
||||
|
||||
/**
|
||||
* If true then a disjunction which means outer joins are required.
|
||||
*/
|
||||
private final boolean disjunction;
|
||||
|
||||
JunctionExpression(Query<T> query, TextExpressionList<T> parent) {
|
||||
this.disjunction = true;
|
||||
this.joinType = OR;
|
||||
JunctionExpression(Junction.Type type, Query<T> query, ExpressionList<T> parent) {
|
||||
this.type = type;
|
||||
this.exprList = new DefaultExpressionList<T>(query, parent);
|
||||
}
|
||||
|
||||
JunctionExpression(boolean disjunction, String joinType, Query<T> query, ExpressionList<T> parent) {
|
||||
this.disjunction = disjunction;
|
||||
this.joinType = joinType;
|
||||
this.exprList = new DefaultExpressionList<T>(query, (TextExpressionList<T>)parent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct for copyForPlanKey.
|
||||
*/
|
||||
JunctionExpression(boolean disjunction, String joinType, DefaultExpressionList<T> exprList) {
|
||||
this.disjunction = disjunction;
|
||||
this.joinType = joinType;
|
||||
JunctionExpression(Junction.Type type, DefaultExpressionList<T> exprList) {
|
||||
this.type = type;
|
||||
this.exprList = exprList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeDocQuery(DocQueryContext context) throws IOException {
|
||||
context.startBool(!disjunction);
|
||||
context.startBool(type == Type.AND);
|
||||
List<SpiExpression> list = exprList.internalList();
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
list.get(i).writeDocQuery(context);
|
||||
@@ -96,6 +99,16 @@ abstract class JunctionExpression<T> implements Junction<T>, SpiExpression, Expr
|
||||
context.endBool();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeDocQueryJunction(DocQueryContext context) throws IOException {
|
||||
context.startBoolGroupList(type);
|
||||
List<SpiExpression> list = exprList.internalList();
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
list.get(i).writeDocQuery(context);
|
||||
}
|
||||
context.endBoolGroupList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void containsMany(BeanDescriptor<?> desc, ManyWhereJoins manyWhereJoin) {
|
||||
|
||||
@@ -103,7 +116,7 @@ abstract class JunctionExpression<T> implements Junction<T>, SpiExpression, Expr
|
||||
|
||||
// get the current state for 'require outer joins'
|
||||
boolean parentOuterJoins = manyWhereJoin.isRequireOuterJoins();
|
||||
if (disjunction) {
|
||||
if (type == Type.OR) {
|
||||
// turn on outer joins required for disjunction expressions
|
||||
manyWhereJoin.setRequireOuterJoins(true);
|
||||
}
|
||||
@@ -111,7 +124,7 @@ abstract class JunctionExpression<T> implements Junction<T>, SpiExpression, Expr
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
list.get(i).containsMany(desc, manyWhereJoin);
|
||||
}
|
||||
if (disjunction && !parentOuterJoins) {
|
||||
if (type == Type.OR && !parentOuterJoins) {
|
||||
// restore state to not forcing outer joins
|
||||
manyWhereJoin.setRequireOuterJoins(false);
|
||||
}
|
||||
@@ -155,7 +168,7 @@ abstract class JunctionExpression<T> implements Junction<T>, SpiExpression, Expr
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
SpiExpression item = list.get(i);
|
||||
if (i > 0) {
|
||||
request.append(joinType);
|
||||
request.append(type.literal());
|
||||
}
|
||||
item.addSql(request);
|
||||
}
|
||||
@@ -177,7 +190,7 @@ abstract class JunctionExpression<T> implements Junction<T>, SpiExpression, Expr
|
||||
*/
|
||||
@Override
|
||||
public void queryPlanHash(HashQueryPlanBuilder builder) {
|
||||
builder.add(JunctionExpression.class).add(joinType);
|
||||
builder.add(JunctionExpression.class).add(type);
|
||||
List<SpiExpression> list = exprList.internalList();
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
list.get(i).queryPlanHash(builder);
|
||||
@@ -204,15 +217,82 @@ abstract class JunctionExpression<T> implements Junction<T>, SpiExpression, Expr
|
||||
}
|
||||
|
||||
JunctionExpression that = (JunctionExpression) other;
|
||||
return joinType.equals(that.joinType)
|
||||
&& exprList.isSameByPlan(that.exprList);
|
||||
return type == that.type && exprList.isSameByPlan(that.exprList);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSameByBind(SpiExpression other) {
|
||||
JunctionExpression that = (JunctionExpression) other;
|
||||
return joinType.equals(that.joinType)
|
||||
&& exprList.isSameByBind(that.exprList);
|
||||
return type == that.type && exprList.isSameByBind(that.exprList);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> match(String propertyName, String search) {
|
||||
return match(propertyName, search, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> match(String propertyName, String search, Match options) {
|
||||
return exprList.match(propertyName, search, options);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> multiMatch(String query, String... properties) {
|
||||
return exprList.multiMatch(query, properties);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> multiMatch(String query, MultiMatch options) {
|
||||
return exprList.multiMatch(query, options);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> textSimple(String search, TextSimple options) {
|
||||
return exprList.textSimple(search, options);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> textQueryString(String search, TextQueryString options) {
|
||||
return exprList.textQueryString(search, options);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> textCommonTerms(String search, TextCommonTerms options) {
|
||||
return exprList.textCommonTerms(search, options);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Junction<T> must() {
|
||||
return exprList.must();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Junction<T> should() {
|
||||
return exprList.should();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Junction<T> mustNot() {
|
||||
return exprList.mustNot();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> endMust() {
|
||||
return endTextJunction();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> endShould() {
|
||||
return endTextJunction();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> endMustNot() {
|
||||
return endTextJunction();
|
||||
}
|
||||
|
||||
private ExpressionList<T> endTextJunction() {
|
||||
return exprList.endTextJunction();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1316,7 +1316,7 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextExpressionList text() {
|
||||
public ExpressionList<T> text() {
|
||||
if (textExpressions == null) {
|
||||
useDocStore = true;
|
||||
textExpressions = new DefaultExpressionList<T>(this);
|
||||
|
||||
@@ -77,9 +77,9 @@
|
||||
<logger name="com.avaje.ebean" level="INFO"/>
|
||||
<logger name="org.avaje.ebean" level="INFO"/>
|
||||
|
||||
<!--<logger name="org.avaje.ebean.SQL" level="TRACE"/>-->
|
||||
<!--<logger name="org.avaje.ebean.TXN" level="TRACE"/>-->
|
||||
<!--<logger name="org.avaje.ebean.SUM" level="TRACE"/>-->
|
||||
<logger name="org.avaje.ebean.SQL" level="TRACE"/>
|
||||
<logger name="org.avaje.ebean.TXN" level="TRACE"/>
|
||||
<logger name="org.avaje.ebean.SUM" level="TRACE"/>
|
||||
<!--<logger name="org.avaje.ebean.ELA" level="TRACE"/>-->
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user