diff --git a/src/main/java/com/avaje/ebean/ExpressionFactory.java b/src/main/java/com/avaje/ebean/ExpressionFactory.java index 9c239d870..17bd817d3 100644 --- a/src/main/java/com/avaje/ebean/ExpressionFactory.java +++ b/src/main/java/com/avaje/ebean/ExpressionFactory.java @@ -2,6 +2,9 @@ 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 java.util.Collection; import java.util.List; @@ -298,6 +301,21 @@ public interface ExpressionFactory { */ Expression textMultiMatch(String query, MultiMatch options); + /** + * Create a text simple query expression (currently doc store/Elastic only). + */ + Expression textSimple(String search, TextSimple options); + + /** + * Create a text query string expression (currently doc store/Elastic only). + */ + Expression textQueryString(String search, TextQueryString options); + + /** + * Create a text common terms expression (currently doc store/Elastic only). + */ + Expression textCommonTerms(String search, TextCommonTerms options); + /** * And - join two expressions with a logical and. */ diff --git a/src/main/java/com/avaje/ebean/TextExpressionList.java b/src/main/java/com/avaje/ebean/TextExpressionList.java index b10021e4f..887e5a1ba 100644 --- a/src/main/java/com/avaje/ebean/TextExpressionList.java +++ b/src/main/java/com/avaje/ebean/TextExpressionList.java @@ -2,6 +2,9 @@ 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. @@ -37,6 +40,21 @@ public interface TextExpressionList extends ExpressionList { */ TextExpressionList multiMatch(String search, MultiMatch options); + /** + * Add a simple query string expression. + */ + TextExpressionList textSimple(String search, TextSimple options); + + /** + * Add a query string expression. + */ + TextExpressionList textQueryString(String search, TextQueryString options); + + /** + * Add common terms expression. + */ + TextExpressionList textCommonTerms(String search, TextCommonTerms options); + /** * Start a list of expressions that will be joined by MUST. */ diff --git a/src/main/java/com/avaje/ebean/search/AbstractMatch.java b/src/main/java/com/avaje/ebean/search/AbstractMatch.java index dcd0a6e79..ec019d502 100644 --- a/src/main/java/com/avaje/ebean/search/AbstractMatch.java +++ b/src/main/java/com/avaje/ebean/search/AbstractMatch.java @@ -5,7 +5,7 @@ package com.avaje.ebean.search; */ public abstract class AbstractMatch { - protected boolean and; + protected boolean operatorAnd; protected String analyzer; @@ -28,8 +28,8 @@ public abstract class AbstractMatch { /** * Return true if using the AND operator otherwise using the OR operator. */ - public boolean isAnd() { - return and; + public boolean isOperatorAnd() { + return operatorAnd; } /** diff --git a/src/main/java/com/avaje/ebean/search/Match.java b/src/main/java/com/avaje/ebean/search/Match.java index 03768f81c..a5a23f18d 100644 --- a/src/main/java/com/avaje/ebean/search/Match.java +++ b/src/main/java/com/avaje/ebean/search/Match.java @@ -9,18 +9,7 @@ public class Match extends AbstractMatch { protected boolean phrasePrefix; - /** - * Create and return Match options using AND operator. - */ - public static Match AND() { - return new Match().opAnd(); - } - - /** - * Create and return Match options using OR operator. - */ - public static Match OR() { - return new Match().opOr(); + public Match() { } /** @@ -43,7 +32,7 @@ public class Match extends AbstractMatch { * Use the AND operator (rather than OR). */ public Match opAnd() { - and = true; + operatorAnd = true; return this; } @@ -51,7 +40,7 @@ public class Match extends AbstractMatch { * Use the OR operator (rather than AND). */ public Match opOr() { - and = false; + operatorAnd = false; return this; } diff --git a/src/main/java/com/avaje/ebean/search/MultiMatch.java b/src/main/java/com/avaje/ebean/search/MultiMatch.java index 83ae0f61b..eed065a70 100644 --- a/src/main/java/com/avaje/ebean/search/MultiMatch.java +++ b/src/main/java/com/avaje/ebean/search/MultiMatch.java @@ -16,26 +16,19 @@ public class MultiMatch extends AbstractMatch { PHRASE_PREFIX } - protected Type type = Type.BEST_FIELDS; + protected final String[] fields; - protected String[] fields; + protected Type type = Type.BEST_FIELDS; protected double tieBreaker; /** - * Create and return Match options using AND operator. + * Create with the given fields. */ public static MultiMatch fields(String... fields) { return new MultiMatch(fields); } - /** - * Create and return Match options using OR operator. - */ - public static MultiMatch OR() { - return new MultiMatch().opOr(); - } - /** * Construct with a set of fields. */ @@ -63,7 +56,7 @@ public class MultiMatch extends AbstractMatch { * Use the AND operator (rather than OR). */ public MultiMatch opAnd() { - and = true; + operatorAnd = true; return this; } @@ -71,7 +64,7 @@ public class MultiMatch extends AbstractMatch { * Use the OR operator (rather than AND). */ public MultiMatch opOr() { - and = false; + operatorAnd = false; return this; } diff --git a/src/main/java/com/avaje/ebean/search/TextCommonTerms.java b/src/main/java/com/avaje/ebean/search/TextCommonTerms.java new file mode 100644 index 000000000..c1cad820a --- /dev/null +++ b/src/main/java/com/avaje/ebean/search/TextCommonTerms.java @@ -0,0 +1,141 @@ +package com.avaje.ebean.search; + +/** + * Text common terms query. + *

+ * This maps to an ElasticSearch "common terms query". + *

+ + *
{@code
+ *
+ *  TextCommonTerms options = new TextCommonTerms()
+ *    .cutoffFrequency(0.001)
+ *    .minShouldMatch("50%")
+ *    .lowFreqOperatorAnd(true)
+ *    .highFreqOperatorAnd(true);
+ *
+ *  List customers = server.find(Customer.class)
+ *    .text()
+ *    .textCommonTerms("the brown", options)
+ *    .findList();
+ *
+ * }
+ * + *
{@code
+ *
+ *   // ElasticSearch expression
+ *
+ *   "common": {
+ *     "body": {
+ *       "query": "the brown",
+ *       "cutoff_frequency": 0.001,
+ *       "low_freq_operator": "and",
+ *       "high_freq_operator": "and",
+ *       "minimum_should_match": "50%"
+ *     }
+ *   }
+ *
+ * }
+ */ +public class TextCommonTerms { + + protected double cutoffFrequency; + + protected boolean lowFreqOperatorAnd; + protected boolean highFreqOperatorAnd; + + protected String minShouldMatch; + protected String minShouldMatchLowFreq; + protected String minShouldMatchHighFreq; + + /** + * Set the cutoff frequency. + */ + public TextCommonTerms cutoffFrequency(double cutoffFrequency) { + this.cutoffFrequency = cutoffFrequency; + return this; + } + + /** + * Set to true if low frequency terms should use AND operator. + */ + public TextCommonTerms lowFreqOperatorAnd(boolean opAnd) { + this.lowFreqOperatorAnd = opAnd; + return this; + } + + /** + * Set to true if high frequency terms should use AND operator. + */ + public TextCommonTerms highFreqOperatorAnd(boolean opAnd) { + this.highFreqOperatorAnd = opAnd; + return this; + } + + /** + * Set the minimum should match. + */ + public TextCommonTerms minShouldMatch(String minShouldMatch) { + this.minShouldMatch = minShouldMatch; + return this; + } + + /** + * Set the minimum should match for low frequency terms. + */ + public TextCommonTerms minShouldMatchLowFreq(String minShouldMatchLowFreq) { + this.minShouldMatchLowFreq = minShouldMatchLowFreq; + return this; + } + + /** + * Set the minimum should match for high frequency terms. + */ + public TextCommonTerms minShouldMatchHighFreq(String minShouldMatchHighFreq) { + this.minShouldMatchHighFreq = minShouldMatchHighFreq; + return this; + } + + /** + * Return true if low freq should use the AND operator. + */ + public boolean isLowFreqOperatorAnd() { + return lowFreqOperatorAnd; + } + + /** + * Return true if high freq should use the AND operator. + */ + public boolean isHighFreqOperatorAnd() { + return highFreqOperatorAnd; + } + + /** + * Return the cutoff frequency. + */ + public double getCutoffFrequency() { + return cutoffFrequency; + } + + /** + * Return the minimum to match. + */ + public String getMinShouldMatch() { + return minShouldMatch; + } + + /** + * Return the minimum to match for high frequency. + */ + public String getMinShouldMatchHighFreq() { + return minShouldMatchHighFreq; + } + + /** + * Return the minimum to match for low frequency. + */ + public String getMinShouldMatchLowFreq() { + return minShouldMatchLowFreq; + } + +} diff --git a/src/main/java/com/avaje/ebean/search/TextQueryString.java b/src/main/java/com/avaje/ebean/search/TextQueryString.java new file mode 100644 index 000000000..a50af6ff1 --- /dev/null +++ b/src/main/java/com/avaje/ebean/search/TextQueryString.java @@ -0,0 +1,436 @@ +package com.avaje.ebean.search; + +/** + * Text query string options. + *

+ * This maps to an ElasticSearch "query string query". + *

+ * + *
{@code
+ *
+ *  TextQueryString options = new TextQueryString()
+ *       .analyzeWildcard(true)
+ *       .fields("name")
+ *       .lenient(true)
+ *       .opAnd();
+ *
+ *   List customers = server.find(Customer.class)
+ *       .text()
+ *       .textSimple("quick brown", options)
+ *       .findList();
+ *
+ * }
+ * + * + *
{@code
+ *
+ *  // just use default options
+ *  TextQueryString options = new TextQueryString();
+ *
+ *   List customers = server.find(Customer.class)
+ *       .text()
+ *       .textSimple("quick brown", options)
+ *       .findList();
+ *
+ * }
+ * + */ +public class TextQueryString { + + public static final int DEFAULT_FUZZY_MAX_EXPANSIONS = 50; + public static final int DEFAULT_MAX_DETERMINIZED_STATES = 10000; + + protected final String[] fields; + + /** + * Only used when multiple fields set. + */ + protected boolean useDisMax = true; + + /** + * Only used when multiple fields set. + */ + protected double tieBreaker; + + protected String defaultField; + + protected boolean operatorAnd; + + protected String analyzer; + + protected boolean allowLeadingWildcard = true; + + protected boolean lowercaseExpandedTerms = true; + + protected boolean enablePositionIncrements = true; + + protected int fuzzyMaxExpansions = DEFAULT_FUZZY_MAX_EXPANSIONS; + + protected String fuzziness; + + protected int fuzzyPrefixLength; + + protected double phraseSlop; + + protected double boost; + + protected boolean analyzeWildcard; + + protected boolean autoGeneratePhraseQueries; + + protected int maxDeterminizedStates = DEFAULT_MAX_DETERMINIZED_STATES; + + protected String minShouldMatch; + + protected boolean lenient; + + protected String locale; + + protected String timeZone; + + protected String rewrite; + + /** + * Create with given fields. + */ + public static TextQueryString fields(String... fields) { + return new TextQueryString(fields); + } + + /** + * Construct with the fields to use. + */ + public TextQueryString(String... fields) { + this.fields = fields; + } + + /** + * Use the AND operator (rather than OR). + */ + public TextQueryString opAnd() { + this.operatorAnd = true; + return this; + } + + /** + * Use the OR operator (rather than AND). + */ + public TextQueryString opOr() { + this.operatorAnd = false; + return this; + } + + /** + * Set the locale. + */ + public TextQueryString locale(String locale) { + this.locale = locale; + return this; + } + + /** + * Set lenient mode. + */ + public TextQueryString lenient(boolean lenient) { + this.lenient = lenient; + return this; + } + + /** + * Set the minimum should match. + */ + public TextQueryString minShouldMatch(String minShouldMatch) { + this.minShouldMatch = minShouldMatch; + return this; + } + + /** + * Set the analyzer. + */ + public TextQueryString analyzer(String analyzer) { + this.analyzer = analyzer; + return this; + } + + /** + * Set useDisMax option (when multiple fields only). + */ + public TextQueryString useDisMax(boolean useDisMax) { + this.useDisMax = useDisMax; + return this; + } + + /** + * Set tieBreaker option (when multiple fields only). + */ + public TextQueryString tieBreaker(double tieBreaker) { + this.tieBreaker = tieBreaker; + return this; + } + + /** + * Set the default field. + */ + public TextQueryString defaultField(String defaultField) { + this.defaultField = defaultField; + return this; + } + + /** + * Set allow leading wildcard mode. + */ + public TextQueryString allowLeadingWildcard(boolean allowLeadingWildcard) { + this.allowLeadingWildcard = allowLeadingWildcard; + return this; + } + + /** + * Set lowercase expanded terms mode. + */ + public TextQueryString lowercaseExpandedTerms(boolean lowercaseExpandedTerms) { + this.lowercaseExpandedTerms = lowercaseExpandedTerms; + return this; + } + + /** + * Set enable position increments mode. + */ + public TextQueryString enablePositionIncrements(boolean enablePositionIncrements) { + this.enablePositionIncrements = enablePositionIncrements; + return this; + } + + /** + * Set fuzzy max expansions. + */ + public TextQueryString fuzzyMaxExpansions(int fuzzyMaxExpansions) { + this.fuzzyMaxExpansions = fuzzyMaxExpansions; + return this; + } + + /** + * Set fuzziness. + */ + public TextQueryString fuzziness(String fuzziness) { + this.fuzziness = fuzziness; + return this; + } + + /** + * Set the fuzzy prefix length. + */ + public TextQueryString fuzzyPrefixLength(int fuzzyPrefixLength) { + this.fuzzyPrefixLength = fuzzyPrefixLength; + return this; + } + + /** + * Set the phrase slop. + */ + public TextQueryString phraseSlop(double phraseSlop) { + this.phraseSlop = phraseSlop; + return this; + } + + /** + * Set the boost. + */ + public TextQueryString boost(double boost) { + this.boost = boost; + return this; + } + + /** + * Set the analyze wildcard mode. + */ + public TextQueryString analyzeWildcard(boolean analyzeWildcard) { + this.analyzeWildcard = analyzeWildcard; + return this; + } + /** + * Set the auto generate phrase queries mode. + */ + public TextQueryString autoGeneratePhraseQueries(boolean autoGeneratePhraseQueries) { + this.autoGeneratePhraseQueries = autoGeneratePhraseQueries; + return this; + } + + /** + * Set the max determinized states. + */ + public TextQueryString maxDeterminizedStates(int maxDeterminizedStates) { + this.maxDeterminizedStates = maxDeterminizedStates; + return this; + } + + /** + * Set the time zone. + */ + public TextQueryString timeZone(String timeZone) { + this.timeZone = timeZone; + return this; + } + + /** + * Set the rewrite option. + */ + public TextQueryString rewrite(String rewrite) { + this.rewrite = rewrite; + return this; + } + + /** + * Return the rewrite option. + */ + public String getRewrite() { + return rewrite; + } + + /** + * Return the fields. + */ + public String[] getFields() { + return fields; + } + + /** + * Return true if AND is the default operator. + */ + public boolean isOperatorAnd() { + return operatorAnd; + } + + /** + * Return the analyzer. + */ + public String getAnalyzer() { + return analyzer; + } + + /** + * Return the locale. + */ + public String getLocale() { + return locale; + } + + /** + * Return lenient mode. + */ + public boolean isLenient() { + return lenient; + } + + /** + * Return the minimum should match. + */ + public String getMinShouldMatch() { + return minShouldMatch; + } + + /** + * Return the useDixMax mode. + */ + public boolean isUseDisMax() { + return useDisMax; + } + + /** + * Return the tie breaker. + */ + public double getTieBreaker() { + return tieBreaker; + } + + /** + * Return the default field. + */ + public String getDefaultField() { + return defaultField; + } + + /** + * Return the allow leading wildcard mode. + */ + public boolean isAllowLeadingWildcard() { + return allowLeadingWildcard; + } + + /** + * Return the lowercase expanded terms mode. + */ + public boolean isLowercaseExpandedTerms() { + return lowercaseExpandedTerms; + } + + /** + * Return the enable position increments mode. + */ + public boolean isEnablePositionIncrements() { + return enablePositionIncrements; + } + + /** + * Return the fuzzy max expansions. + */ + public int getFuzzyMaxExpansions() { + return fuzzyMaxExpansions; + } + + /** + * Return the fuzziness. + */ + public String getFuzziness() { + return fuzziness; + } + + /** + * Return the fuzzy prefix length. + */ + public int getFuzzyPrefixLength() { + return fuzzyPrefixLength; + } + + /** + * Return the phrase slop. + */ + public double getPhraseSlop() { + return phraseSlop; + } + + /** + * Return the analyze wildcard mode. + */ + public boolean isAnalyzeWildcard() { + return analyzeWildcard; + } + + /** + * Return the boost. + */ + public double getBoost() { + return boost; + } + + /** + * Return the auto generate phase queries mode. + */ + public boolean isAutoGeneratePhraseQueries() { + return autoGeneratePhraseQueries; + } + + /** + * Return the max determinized states. + */ + public int getMaxDeterminizedStates() { + return maxDeterminizedStates; + } + + /** + * Return the time zone. + */ + public String getTimeZone() { + return timeZone; + } + +} diff --git a/src/main/java/com/avaje/ebean/search/TextSimple.java b/src/main/java/com/avaje/ebean/search/TextSimple.java new file mode 100644 index 000000000..789f764ba --- /dev/null +++ b/src/main/java/com/avaje/ebean/search/TextSimple.java @@ -0,0 +1,194 @@ +package com.avaje.ebean.search; + +/** + * Simple text query options. + *

+ * This maps to an ElasticSearch "simple text query". + *

+ * + *
{@code
+ *
+ *  TextSimple options = new TextSimple()
+ *       .analyzeWildcard(true)
+ *       .fields("name")
+ *       .lenient(true)
+ *       .opAnd();
+ *
+ *   List customers = server.find(Customer.class)
+ *       .text()
+ *       .textSimple("quick brown", options)
+ *       .findList();
+ *
+ * }
+ */ +public class TextSimple { + + protected String[] fields; + + protected boolean operatorAnd; + + protected String analyzer; + + protected String flags; + + protected boolean lowercaseExpandedTerms = true; + + protected boolean analyzeWildcard; + + protected String locale; + + protected boolean lenient; + + protected String minShouldMatch; + + /** + * Construct + */ + public TextSimple() { + } + + /** + * Set the fields. + */ + public TextSimple fields(String... fields) { + this.fields = fields; + return this; + } + + /** + * Use AND as the default operator. + */ + public TextSimple opAnd() { + this.operatorAnd = true; + return this; + } + + /** + * Use OR as the default operator. + */ + public TextSimple opOr() { + this.operatorAnd = false; + return this; + } + + /** + * Set the analyzer + */ + public TextSimple analyzer(String analyzer) { + this.analyzer = analyzer; + return this; + } + + /** + * Set the flags. + */ + public TextSimple flags(String flags) { + this.flags = flags; + return this; + } + + + /** + * Set the false to not use lowercase expanded terms. + */ + public TextSimple lowercaseExpandedTerms(boolean lowercaseExpandedTerms) { + this.lowercaseExpandedTerms = lowercaseExpandedTerms; + return this; + } + + /** + * Set to true to use analyze wildcard. + */ + public TextSimple analyzeWildcard(boolean analyzeWildcard) { + this.analyzeWildcard = analyzeWildcard; + return this; + } + + /** + * Set the locale. + */ + public TextSimple locale(String locale) { + this.locale = locale; + return this; + } + + /** + * Set the lenient mode. + */ + public TextSimple lenient(boolean lenient) { + this.lenient = lenient; + return this; + } + + /** + * Set the minimum should match. + */ + public TextSimple minShouldMatch(String minShouldMatch) { + this.minShouldMatch = minShouldMatch; + return this; + } + + /** + * Return lenient mode. + */ + public boolean isLenient() { + return lenient; + } + + /** + * Return true to analyse wildcard. + */ + public boolean isAnalyzeWildcard() { + return analyzeWildcard; + } + + /** + * Return lowercase expanded terms mode. + */ + public boolean isLowercaseExpandedTerms() { + return lowercaseExpandedTerms; + } + + /** + * Return true if the default operator should be AND. + */ + public boolean isOperatorAnd() { + return operatorAnd; + } + + /** + * Return the analyzer to use. + */ + public String getAnalyzer() { + return analyzer; + } + + /** + * Return the fields. + */ + public String[] getFields() { + return fields; + } + + /** + * Return the locale. + */ + public String getLocale() { + return locale; + } + + /** + * Return the flags. + */ + public String getFlags() { + return flags; + } + + /** + * Return the minimum should match. + */ + public String getMinShouldMatch() { + return minShouldMatch; + } + +} diff --git a/src/main/java/com/avaje/ebeaninternal/server/expression/DTextJunction.java b/src/main/java/com/avaje/ebeaninternal/server/expression/DTextJunction.java index 50a66c8f7..60ec67bb7 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/expression/DTextJunction.java +++ b/src/main/java/com/avaje/ebeaninternal/server/expression/DTextJunction.java @@ -5,6 +5,9 @@ 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; @@ -58,6 +61,21 @@ class DTextJunction extends JunctionExpression implements SpiTextJunction< return exprList.multiMatch(query, options); } + @Override + public TextExpressionList textSimple(String search, TextSimple options) { + return exprList.textSimple(search, options); + } + + @Override + public TextExpressionList textQueryString(String search, TextQueryString options) { + return exprList.textQueryString(search, options); + } + + @Override + public TextExpressionList textCommonTerms(String search, TextCommonTerms options) { + return exprList.textCommonTerms(search, options); + } + @Override public TextJunction must() { return exprList.must(); diff --git a/src/main/java/com/avaje/ebeaninternal/server/expression/DefaultExpressionFactory.java b/src/main/java/com/avaje/ebeaninternal/server/expression/DefaultExpressionFactory.java index 841f259ff..c57c9c9dd 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/expression/DefaultExpressionFactory.java +++ b/src/main/java/com/avaje/ebeaninternal/server/expression/DefaultExpressionFactory.java @@ -12,6 +12,9 @@ import com.avaje.ebean.TextJunction; import com.avaje.ebean.bean.EntityBean; 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.SpiExpressionFactory; import com.avaje.ebeaninternal.api.SpiQuery; @@ -50,6 +53,21 @@ public class DefaultExpressionFactory implements SpiExpressionFactory { return new TextMultiMatchExpression(query, options); } + @Override + public Expression textSimple(String search, TextSimple options) { + return new TextSimpleExpression(search, options); + } + + @Override + public Expression textQueryString(String search, TextQueryString options) { + return new TextQueryStringExpression(search, options); + } + + @Override + public Expression textCommonTerms(String search, TextCommonTerms options) { + return new TextCommonTermsExpression(search, options); + } + public Expression jsonExists(String propertyName, String path) { return new JsonPathExpression(propertyName, path, Op.EXISTS, null); } diff --git a/src/main/java/com/avaje/ebeaninternal/server/expression/DefaultExpressionList.java b/src/main/java/com/avaje/ebeaninternal/server/expression/DefaultExpressionList.java index 7f8fc4242..2acb66fc8 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/expression/DefaultExpressionList.java +++ b/src/main/java/com/avaje/ebeaninternal/server/expression/DefaultExpressionList.java @@ -4,6 +4,9 @@ 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; @@ -876,6 +879,24 @@ public class DefaultExpressionList implements SpiExpressionList, SpiTextEx return this; } + @Override + public TextExpressionList textSimple(String search, TextSimple options) { + add(expr.textSimple(search, options)); + return this; + } + + @Override + public TextExpressionList textQueryString(String search, TextQueryString options) { + add(expr.textQueryString(search, options)); + return this; + } + + @Override + public TextExpressionList textCommonTerms(String search, TextCommonTerms options) { + add(expr.textCommonTerms(search, options)); + return this; + } + @Override public TextJunction must() { return textJunction(TextJunction.Type.MUST); diff --git a/src/main/java/com/avaje/ebeaninternal/server/expression/DocQueryContext.java b/src/main/java/com/avaje/ebeaninternal/server/expression/DocQueryContext.java index 8a66d3bf1..b289c6768 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/expression/DocQueryContext.java +++ b/src/main/java/com/avaje/ebeaninternal/server/expression/DocQueryContext.java @@ -4,6 +4,9 @@ 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; +import com.avaje.ebean.search.TextQueryString; +import com.avaje.ebean.search.TextSimple; import java.io.IOException; import java.util.List; @@ -104,6 +107,21 @@ public interface DocQueryContext { */ void writeMultiMatch(String search, MultiMatch options) throws IOException; + /** + * Write a simple expression. + */ + void writeTextSimple(String search, TextSimple options) throws IOException; + + /** + * Write a common terms expression. + */ + void writeTextCommonTerms(String search, TextCommonTerms options) throws IOException; + + /** + * Write a query string expression. + */ + void writeTextQueryString(String search, TextQueryString options) throws IOException; + /** * Start a Bool which may contain some of Must, Must Not, Should. */ diff --git a/src/main/java/com/avaje/ebeaninternal/server/expression/TextCommonTermsExpression.java b/src/main/java/com/avaje/ebeaninternal/server/expression/TextCommonTermsExpression.java new file mode 100644 index 000000000..f75dd9f3e --- /dev/null +++ b/src/main/java/com/avaje/ebeaninternal/server/expression/TextCommonTermsExpression.java @@ -0,0 +1,27 @@ +package com.avaje.ebeaninternal.server.expression; + +import com.avaje.ebean.search.TextCommonTerms; + +import java.io.IOException; + +/** + * Full text common terms expression. + */ +class TextCommonTermsExpression extends AbstractTextExpression { + + private final String search; + + private final TextCommonTerms options; + + public TextCommonTermsExpression(String search, TextCommonTerms options) { + super(null); + this.search = search; + this.options = options; + } + + @Override + public void writeDocQuery(DocQueryContext context) throws IOException { + context.writeTextCommonTerms(search, options); + } + +} diff --git a/src/main/java/com/avaje/ebeaninternal/server/expression/TextQueryStringExpression.java b/src/main/java/com/avaje/ebeaninternal/server/expression/TextQueryStringExpression.java new file mode 100644 index 000000000..128f67954 --- /dev/null +++ b/src/main/java/com/avaje/ebeaninternal/server/expression/TextQueryStringExpression.java @@ -0,0 +1,27 @@ +package com.avaje.ebeaninternal.server.expression; + +import com.avaje.ebean.search.TextQueryString; + +import java.io.IOException; + +/** + * Full text query string expression. + */ +class TextQueryStringExpression extends AbstractTextExpression { + + private final String search; + + private final TextQueryString options; + + public TextQueryStringExpression(String search, TextQueryString options) { + super(null); + this.search = search; + this.options = options; + } + + @Override + public void writeDocQuery(DocQueryContext context) throws IOException { + context.writeTextQueryString(search, options); + } + +} diff --git a/src/main/java/com/avaje/ebeaninternal/server/expression/TextSimpleExpression.java b/src/main/java/com/avaje/ebeaninternal/server/expression/TextSimpleExpression.java new file mode 100644 index 000000000..34fd1ec82 --- /dev/null +++ b/src/main/java/com/avaje/ebeaninternal/server/expression/TextSimpleExpression.java @@ -0,0 +1,27 @@ +package com.avaje.ebeaninternal.server.expression; + +import com.avaje.ebean.search.TextSimple; + +import java.io.IOException; + +/** + * Full text Multi-Match expression. + */ +class TextSimpleExpression extends AbstractTextExpression { + + private final String search; + + private final TextSimple options; + + public TextSimpleExpression(String search, TextSimple options) { + super(null); + this.search = search; + this.options = options; + } + + @Override + public void writeDocQuery(DocQueryContext context) throws IOException { + context.writeTextSimple(search, options); + } + +} diff --git a/src/test/java/com/avaje/ebean/TextExpressionListTest.java b/src/test/java/com/avaje/ebean/TextExpressionListTest.java index c6b136323..fec23efd8 100644 --- a/src/test/java/com/avaje/ebean/TextExpressionListTest.java +++ b/src/test/java/com/avaje/ebean/TextExpressionListTest.java @@ -37,7 +37,7 @@ public class TextExpressionListTest { .match("title", "war and peace") .match("author", "leo tolstoy") .should() - .match("translator", "Constance Garnett", Match.AND().boost(2).minShouldMatch("75%")) + .match("translator", "Constance Garnett", new Match().opAnd().boost(2).minShouldMatch("75%")) .match("translator", "Louise Maude") .where() .gt("reviewDate", 12345); diff --git a/src/test/resources/junk.json b/src/test/resources/junk.json index 3f6199367..06b9aa330 100644 --- a/src/test/resources/junk.json +++ b/src/test/resources/junk.json @@ -1,22 +1,23 @@ { - "fields": [ - "status", - "customer.name", - "details.product.id" - ], "query": { - "filtered": { - "filter": { - "bool": { - "must": [ - { - "match": { - "customer.name": "Rob" - } - } - ] - } - } + "query_string": { + "query": "brown", + "default_field": "name", + "default_operator": "and", + "analyzer": "whitespace", + "allow_leading_wildcard": false, + "lowercase_expanded_terms": false, + "enable_position_increments": false, + "fuzzy_max_expansions": 10, + "fuzziness": "1", + "fuzzy_prefix_length": 3, + "boost": 2.0, + "analyze_wildcard": false, + "auto_generate_phrase_queries": true, + "max_determinized_states": 500, + "minimum_should_match": "1", + "lenient": true, + "locale": "EN" } } -} \ No newline at end of file +}