Polishing.

Add support for Pattern. Extract Regex flags translation from Criteria into RegexFlags utility class. Add since and author tags. Simplify tests. Update reference documentation.

See #3725.
Original pull request: #3781.
This commit is contained in:
Mark Paluch
2021-08-26 12:20:11 +02:00
parent 297ef98239
commit 69b582823a
7 changed files with 786 additions and 529 deletions

View File

@@ -18,8 +18,11 @@ package org.springframework.data.mongodb.core.aggregation;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
import org.springframework.data.domain.Range;
import org.springframework.data.mongodb.util.RegexFlags;
import org.springframework.util.Assert;
/**
@@ -27,6 +30,7 @@ import org.springframework.util.Assert;
*
* @author Christoph Strobl
* @author Mark Paluch
* @author Divya Srivastava
* @since 1.10
*/
public class StringOperators {
@@ -515,117 +519,170 @@ public class StringOperators {
private RTrim createRTrim() {
return usesFieldRef() ? RTrim.valueOf(fieldReference) : RTrim.valueOf(expression);
}
/**
* Creates new {@link AggregationExpression} that takes the associated string representation and applies the given
* Creates new {@link AggregationExpression} that takes the associated string representation and applies the given
* regular expression to find the document with the first match.<br />
* <strong>NOTE:</strong> Requires MongoDB 4.0 or later.
*
* @param regex must not be {@literal null}.
* @return new instance of {@link RegexFind}.
* @since 3.3
*/
public RegexFind regexFind(String regex) {
return createRegexFind().regex(regex);
}
/**
* Creates new {@link AggregationExpression} that takes the associated string representation and applies the regular
* expression resulting from the given {@link AggregationExpression} to find the document with the first match.<br />
* Creates new {@link AggregationExpression} that takes the associated string representation and applies the regular
* expression resulting from the given {@link AggregationExpression} to find the document with the first
* match.<br />
* <strong>NOTE:</strong> Requires MongoDB 4.0 or later.
*
* @param expression must not be {@literal null}.
* @return new instance of {@link RegexFind}.
* @since 3.3
*/
public RegexFind regexFind(AggregationExpression expression) {
return createRegexFind().regexOf(expression);
}
/**
* Creates new {@link AggregationExpression} that takes the associated string representation and applies the regular
* Creates new {@link AggregationExpression} that takes the {@link Pattern} and applies the regular expression with
* the options specified in the argument to find the document with the first match.
*
* @param pattern the pattern object to apply.
* @return new instance of {@link RegexFind}.
* @since 3.3
*/
public RegexFind regexFind(Pattern pattern) {
return createRegexFind().pattern(pattern);
}
/**
* Creates new {@link AggregationExpression} that takes the associated string representation and applies the regular
* expression with the options specified in the argument to find the document with the first match.
*
* @param regex the regular expression to apply
* @param options the options to use
* @param regex the regular expression to apply.
* @param options the options to use.
* @return new instance of {@link RegexFind}.
* @since 3.3
*/
public RegexFind regexFind(String regex,String options) {
public RegexFind regexFind(String regex, String options) {
return createRegexFind().regex(regex).options(options);
}
private RegexFind createRegexFind() {
return usesFieldRef() ? RegexFind.valueOf(fieldReference) : RegexFind.valueOf(expression);
}
/**
* Creates new {@link AggregationExpression} that takes the associated string representation and applies the given
* Creates new {@link AggregationExpression} that takes the associated string representation and applies the given
* regular expression to find all the documents with the match.<br />
* <strong>NOTE:</strong> Requires MongoDB 4.0 or later.
*
* @param regex must not be {@literal null}.
* @return new instance of {@link RegexFindAll}.
* @since 3.3
*/
public RegexFindAll regexFindAll(String regex) {
return createRegexFindAll().regex(regex);
}
/**
* Creates new {@link AggregationExpression} that takes the associated string representation and applies the regular
* expression resulting from the given {@link AggregationExpression} to find all the documents with the match..<br />
* Creates new {@link AggregationExpression} that takes the associated string representation and applies the regular
* expression resulting from the given {@link AggregationExpression} to find all the documents with the
* match..<br />
* <strong>NOTE:</strong> Requires MongoDB 4.0 or later.
*
* @param expression must not be {@literal null}.
* @return new instance of {@link RegexFindAll}.
* @since 3.3
*/
public RegexFindAll regexFindAll(AggregationExpression expression) {
return createRegexFindAll().regexOf(expression);
}
/**
* Creates new {@link AggregationExpression} that takes the associated string representation and applies the regular
* expression with the options specified in the argument to find all the documents with the match..
* Creates new {@link AggregationExpression} that takes a {@link Pattern} and applies the regular expression with
* the options specified in the argument to find all the documents with the match.
*
* @param regex the regular expression to apply
* @param options the options to use
* @param pattern the pattern object to apply.
* @return new instance of {@link RegexFindAll}.
* @since 3.3
*/
public RegexFindAll regexFindAll(String regex,String options) {
public RegexFindAll regexFindAll(Pattern pattern) {
return createRegexFindAll().pattern(pattern);
}
/**
* Creates new {@link AggregationExpression} that takes the associated string representation and applies the regular
* expression with the options specified in the argument to find all the documents with the match.
*
* @param regex the regular expression to apply.
* @param options the options to use.
* @return new instance of {@link RegexFindAll}.
* @since 3.3
*/
public RegexFindAll regexFindAll(String regex, String options) {
return createRegexFindAll().regex(regex).options(options);
}
private RegexFindAll createRegexFindAll() {
return usesFieldRef() ? RegexFindAll.valueOf(fieldReference) : RegexFindAll.valueOf(expression);
}
/**
* Creates new {@link AggregationExpression} that takes the associated string representation and applies the given
* Creates new {@link AggregationExpression} that takes the associated string representation and applies the given
* regular expression to find if a match is found or not.<br />
* <strong>NOTE:</strong> Requires MongoDB 4.0 or later.
*
* @param regex must not be {@literal null}.
* @return new instance of {@link RegexMatch}.
* @since 3.3
*/
public RegexMatch regexMatch(String regex) {
return createRegexMatch().regex(regex);
}
/**
* Creates new {@link AggregationExpression} that takes the associated string representation and applies the regular
* Creates new {@link AggregationExpression} that takes the associated string representation and applies the regular
* expression resulting from the given {@link AggregationExpression} to find if a match is found or not.<br />
* <strong>NOTE:</strong> Requires MongoDB 4.0 or later.
*
* @param expression must not be {@literal null}.
* @return new instance of {@link RegexMatch}.
* @since 3.3
*/
public RegexMatch regexMatch(AggregationExpression expression) {
return createRegexMatch().regexOf(expression);
}
/**
* Creates new {@link AggregationExpression} that takes the associated string representation and applies the regular
* Creates new {@link AggregationExpression} that takes a {@link Pattern} and applies the regular expression with
* the options specified in the argument to find if a match is found or not.
*
* @param pattern the pattern object to apply.
* @return new instance of {@link RegexMatch}.
* @since 3.3
*/
public RegexMatch regexMatch(Pattern pattern) {
return createRegexMatch().pattern(pattern);
}
/**
* Creates new {@link AggregationExpression} that takes the associated string representation and applies the regular
* expression with the options specified in the argument to find if a match is found or not.
*
* @param regex the regular expression to apply
* @param options the options to use
* @param regex the regular expression to apply.
* @param options the options to use.
* @return new instance of {@link RegexMatch}.
* @since 3.3
*/
public RegexMatch regexMatch(String regex,String options) {
public RegexMatch regexMatch(String regex, String options) {
return createRegexMatch().regex(regex).options(options);
}
private RegexMatch createRegexMatch() {
return usesFieldRef() ? RegexMatch.valueOf(fieldReference) : RegexMatch.valueOf(expression);
}
@@ -1591,35 +1648,35 @@ public class StringOperators {
return "$rtrim";
}
}
/**
* {@link AggregationExpression} for {@code $regexFind} which applies a regular expression (regex) to a string and
* {@link AggregationExpression} for {@code $regexFind} which applies a regular expression (regex) to a string and
* returns information on the first matched substring. <br />
* <strong>NOTE:</strong> Requires MongoDB 4.0 or later.
*
* @author Divya Srivastava
* @since 3.3
*/
public static class RegexFind extends AbstractAggregationExpression {
protected RegexFind(Object value) {
super(value);
}
@Override
protected String getMongoMethod() {
return "$regexFind";
}
/**
* Creates new {@link RegexFind} using the value of the provided {@link Field fieldReference} as {@literal input} value.
* Creates new {@link RegexFind} using the value of the provided {@link Field fieldReference} as {@literal input}
* value.
*
* @param fieldReference must not be {@literal null}.
* @return new instance of {@link RegexFind}.
*/
public static RegexFind valueOf(String fieldReference) {
Assert.notNull(fieldReference, "FieldReference must not be null!");
return new RegexFind(Collections.singletonMap("input", Fields.field(fieldReference)));
}
/**
* Creates new {@link RegexFind} using the result of the provided {@link AggregationExpression} as {@literal input}
* value.
@@ -1628,10 +1685,12 @@ public class StringOperators {
* @return new instance of {@link RegexFind}.
*/
public static RegexFind valueOf(AggregationExpression expression) {
Assert.notNull(expression, "Expression must not be null!");
return new RegexFind(Collections.singletonMap("input", expression));
}
/**
* Optional specify the options to use with the regular expression.
*
@@ -1639,72 +1698,108 @@ public class StringOperators {
* @return new instance of {@link RegexFind}.
*/
public RegexFind options(String options) {
Assert.notNull(options, "Options must not be null!");
return new RegexFind(append("options", options));
}
/**
* Optional specify the reference to the {@link Field field} holding the options values to use with the regular expression.
* Optional specify the reference to the {@link Field field} holding the options values to use with the regular
* expression.
*
* @param fieldReference must not be {@literal null}.
* @return new instance of {@link RegexFind}.
*/
public RegexFind optionsOf(String fieldReference) {
Assert.notNull(fieldReference, "FieldReference must not be null!");
return new RegexFind(append("options", Fields.field(fieldReference)));
}
/**
* Optional specify the {@link AggregationExpression} evaluating to the options values to use with the regular expression.
* Optional specify the {@link AggregationExpression} evaluating to the options values to use with the regular
* expression.
*
* @param expression must not be {@literal null}.
* @return new instance of {@link RegexFind}.
*/
public RegexFind optionsOf(AggregationExpression expression) {
Assert.notNull(expression, "Expression must not be null!");
return new RegexFind(append("options", expression));
}
/**
* Optional specify the regular expression to apply.
* Specify the regular expression to apply.
*
* @param regex must not be {@literal null}.
* @return new instance of {@link RegexFind}.
*/
public RegexFind regex(String regex) {
Assert.notNull(regex, "Regex must not be null!");
return new RegexFind(append("regex",regex));
return new RegexFind(append("regex", regex));
}
/**
* Optional specify the reference to the {@link Field field} holding the regular expression to apply.
* Apply a {@link Pattern} into {@code regex} and {@code options} fields.
*
* @param pattern must not be {@literal null}.
* @return new instance of {@link RegexFind}.
*/
public RegexFind pattern(Pattern pattern) {
Assert.notNull(pattern, "Pattern must not be null!");
Map<String, Object> regex = append("regex", pattern.pattern());
regex.put("options", RegexFlags.toRegexOptions(pattern.flags()));
return new RegexFind(regex);
}
/**
* Specify the reference to the {@link Field field} holding the regular expression to apply.
*
* @param fieldReference must not be {@literal null}.
* @return new instance of {@link RegexFind}.
*/
public RegexFind regexOf(String fieldReference) {
Assert.notNull(fieldReference, "fieldReference must not be null!");
return new RegexFind(append("regex",Fields.field(fieldReference)));
return new RegexFind(append("regex", Fields.field(fieldReference)));
}
/**
* Optional specify the {@link AggregationExpression} evaluating to the regular expression to apply.
* Specify the {@link AggregationExpression} evaluating to the regular expression to apply.
*
* @param expression must not be {@literal null}.
* @return new instance of {@link RegexFind}.
*/
public RegexFind regexOf(AggregationExpression expression) {
Assert.notNull(expression, "Expression must not be null!");
return new RegexFind(append("regex",expression));
return new RegexFind(append("regex", expression));
}
@Override
protected String getMongoMethod() {
return "$regexFind";
}
}
/**
* {@link AggregationExpression} for {@code $regexFindAll} which applies a regular expression (regex) to a string and
* {@link AggregationExpression} for {@code $regexFindAll} which applies a regular expression (regex) to a string and
* returns information on all the matched substrings. <br />
* <strong>NOTE:</strong> Requires MongoDB 4.0 or later.
*
* @author Divya Srivastava
* @since 3.3
*/
public static class RegexFindAll extends AbstractAggregationExpression {
@@ -1712,13 +1807,9 @@ public class StringOperators {
super(value);
}
@Override
protected String getMongoMethod() {
return "$regexFindAll";
}
/**
* Creates new {@link RegexFindAll} using the value of the provided {@link Field fieldReference} as {@literal input} value.
* Creates new {@link RegexFindAll} using the value of the provided {@link Field fieldReference} as {@literal input}
* value.
*
* @param fieldReference must not be {@literal null}.
* @return new instance of {@link RegexFindAll}.
@@ -1727,19 +1818,21 @@ public class StringOperators {
Assert.notNull(fieldReference, "FieldReference must not be null!");
return new RegexFindAll(Collections.singletonMap("input", Fields.field(fieldReference)));
}
/**
* Creates new {@link RegexFindAll} using the result of the provided {@link AggregationExpression} as {@literal input}
* value.
* Creates new {@link RegexFindAll} using the result of the provided {@link AggregationExpression} as
* {@literal input} value.
*
* @param expression must not be {@literal null}.
* @return new instance of {@link RegexFindAll}.
*/
public static RegexFindAll valueOf(AggregationExpression expression) {
Assert.notNull(expression, "Expression must not be null!");
return new RegexFindAll(Collections.singletonMap("input", expression));
}
/**
* Optional specify the options to use with the regular expression.
*
@@ -1747,72 +1840,108 @@ public class StringOperators {
* @return new instance of {@link RegexFindAll}.
*/
public RegexFindAll options(String options) {
Assert.notNull(options, "Options must not be null!");
return new RegexFindAll(append("options", options));
}
/**
* Optional specify the reference to the {@link Field field} holding the options values to use with the regular expression.
* Optional specify the reference to the {@link Field field} holding the options values to use with the regular
* expression.
*
* @param fieldReference must not be {@literal null}.
* @return new instance of {@link RegexFindAll}.
*/
public RegexFindAll optionsOf(String fieldReference) {
Assert.notNull(fieldReference, "fieldReference must not be null!");
return new RegexFindAll(append("options", Fields.field(fieldReference)));
}
/**
* Optional specify the {@link AggregationExpression} evaluating to the options values to use with the regular expression.
* Optional specify the {@link AggregationExpression} evaluating to the options values to use with the regular
* expression.
*
* @param expression must not be {@literal null}.
* @return new instance of {@link RegexFindAll}.
*/
public RegexFindAll optionsOf(AggregationExpression expression) {
Assert.notNull(expression, "Expression must not be null!");
return new RegexFindAll(append("options", expression));
}
/**
* Optional specify the regular expression to apply.
* Apply a {@link Pattern} into {@code regex} and {@code options} fields.
*
* @param pattern must not be {@literal null}.
* @return new instance of {@link RegexFindAll}.
*/
public RegexFindAll pattern(Pattern pattern) {
Assert.notNull(pattern, "Pattern must not be null!");
Map<String, Object> regex = append("regex", pattern.pattern());
regex.put("options", RegexFlags.toRegexOptions(pattern.flags()));
return new RegexFindAll(regex);
}
/**
* Specify the regular expression to apply.
*
* @param regex must not be {@literal null}.
* @return new instance of {@link RegexFindAll}.
*/
public RegexFindAll regex(String regex) {
Assert.notNull(regex, "Regex must not be null!");
return new RegexFindAll(append("regex",regex));
return new RegexFindAll(append("regex", regex));
}
/**
* Optional specify the reference to the {@link Field field} holding the regular expression to apply.
* Specify the reference to the {@link Field field} holding the regular expression to apply.
*
* @param fieldReference must not be {@literal null}.
* @return new instance of {@link RegexFindAll}.
*/
public RegexFindAll regexOf(String fieldReference) {
Assert.notNull(fieldReference, "fieldReference must not be null!");
return new RegexFindAll(append("regex",Fields.field(fieldReference)));
return new RegexFindAll(append("regex", Fields.field(fieldReference)));
}
/**
* Optional specify the {@link AggregationExpression} evaluating to the regular expression to apply.
* Specify the {@link AggregationExpression} evaluating to the regular expression to apply.
*
* @param expression must not be {@literal null}.
* @return new instance of {@link RegexFindAll}.
*/
public RegexFindAll regexOf(AggregationExpression expression) {
Assert.notNull(expression, "Expression must not be null!");
return new RegexFindAll(append("regex",expression));
return new RegexFindAll(append("regex", expression));
}
@Override
protected String getMongoMethod() {
return "$regexFindAll";
}
}
/**
* {@link AggregationExpression} for {@code $regexMatch} which applies a regular expression (regex) to a string and
* {@link AggregationExpression} for {@code $regexMatch} which applies a regular expression (regex) to a string and
* returns a boolean that indicates if a match is found or not. <br />
* <strong>NOTE:</strong> Requires MongoDB 4.0 or later.
*
* @author Divya Srivastava
* @since 3.3
*/
public static class RegexMatch extends AbstractAggregationExpression {
@@ -1820,22 +1949,20 @@ public class StringOperators {
super(value);
}
@Override
protected String getMongoMethod() {
return "$regexMatch";
}
/**
* Creates new {@link RegexMatch} using the value of the provided {@link Field fieldReference} as {@literal input} value.
* Creates new {@link RegexMatch} using the value of the provided {@link Field fieldReference} as {@literal input}
* value.
*
* @param fieldReference must not be {@literal null}.
* @return new instance of {@link RegexMatch}.
*/
public static RegexMatch valueOf(String fieldReference) {
Assert.notNull(fieldReference, "FieldReference must not be null!");
return new RegexMatch(Collections.singletonMap("input", Fields.field(fieldReference)));
}
/**
* Creates new {@link RegexMatch} using the result of the provided {@link AggregationExpression} as {@literal input}
* value.
@@ -1844,10 +1971,12 @@ public class StringOperators {
* @return new instance of {@link RegexMatch}.
*/
public static RegexMatch valueOf(AggregationExpression expression) {
Assert.notNull(expression, "Expression must not be null!");
return new RegexMatch(Collections.singletonMap("input", expression));
}
/**
* Optional specify the options to use with the regular expression.
*
@@ -1855,54 +1984,82 @@ public class StringOperators {
* @return new instance of {@link RegexMatch}.
*/
public RegexMatch options(String options) {
Assert.notNull(options, "Options must not be null!");
return new RegexMatch(append("options", options));
}
/**
* Optional specify the reference to the {@link Field field} holding the options values to use with the regular expression.
* Optional specify the reference to the {@link Field field} holding the options values to use with the regular
* expression.
*
* @param fieldReference must not be {@literal null}.
* @return new instance of {@link RegexMatch}.
*/
public RegexMatch optionsOf(String fieldReference) {
Assert.notNull(fieldReference, "FieldReference must not be null!");
return new RegexMatch(append("options", Fields.field(fieldReference)));
}
/**
* Optional specify the {@link AggregationExpression} evaluating to the options values to use with the regular expression.
* Optional specify the {@link AggregationExpression} evaluating to the options values to use with the regular
* expression.
*
* @param expression must not be {@literal null}.
* @return new instance of {@link RegexMatch}.
*/
public RegexMatch optionsOf(AggregationExpression expression) {
Assert.notNull(expression, "Expression must not be null!");
return new RegexMatch(append("options", expression));
}
/**
* Optional specify the regular expression to apply.
* Apply a {@link Pattern} into {@code regex} and {@code options} fields.
*
* @param pattern must not be {@literal null}.
* @return new instance of {@link RegexMatch}.
*/
public RegexMatch pattern(Pattern pattern) {
Assert.notNull(pattern, "Pattern must not be null!");
Map<String, Object> regex = append("regex", pattern.pattern());
regex.put("options", RegexFlags.toRegexOptions(pattern.flags()));
return new RegexMatch(regex);
}
/**
* Specify the regular expression to apply.
*
* @param regex must not be {@literal null}.
* @return new instance of {@link RegexMatch}.
*/
public RegexMatch regex(String regex) {
Assert.notNull(regex, "Regex must not be null!");
return new RegexMatch(append("regex",regex));
return new RegexMatch(append("regex", regex));
}
/**
* Optional specify the reference to the {@link Field field} holding the regular expression to apply.
* Specify the reference to the {@link Field field} holding the regular expression to apply.
*
* @param fieldReference must not be {@literal null}.
* @return new instance of {@link RegexMatch}.
*/
public RegexMatch regexOf(String fieldReference) {
Assert.notNull(fieldReference, "FieldReference must not be null!");
return new RegexMatch(append("regex",Fields.field(fieldReference)));
return new RegexMatch(append("regex", Fields.field(fieldReference)));
}
/**
* Optional specify the {@link AggregationExpression} evaluating to the regular expression to apply.
*
@@ -1910,9 +2067,15 @@ public class StringOperators {
* @return new instance of {@link RegexMatch}.
*/
public RegexMatch regexOf(AggregationExpression expression) {
Assert.notNull(expression, "Expression must not be null!");
return new RegexMatch(append("regex",expression));
return new RegexMatch(append("regex", expression));
}
@Override
protected String getMongoMethod() {
return "$regexMatch";
}
}
}

View File

@@ -42,6 +42,7 @@ import org.springframework.data.mongodb.core.geo.Sphere;
import org.springframework.data.mongodb.core.schema.JsonSchemaObject.Type;
import org.springframework.data.mongodb.core.schema.JsonSchemaProperty;
import org.springframework.data.mongodb.core.schema.MongoJsonSchema;
import org.springframework.data.mongodb.util.RegexFlags;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.Base64Utils;
@@ -71,20 +72,6 @@ public class Criteria implements CriteriaDefinition {
*/
private static final Object NOT_SET = new Object();
private static final int[] FLAG_LOOKUP = new int[Character.MAX_VALUE];
static {
FLAG_LOOKUP['g'] = 256;
FLAG_LOOKUP['i'] = Pattern.CASE_INSENSITIVE;
FLAG_LOOKUP['m'] = Pattern.MULTILINE;
FLAG_LOOKUP['s'] = Pattern.DOTALL;
FLAG_LOOKUP['c'] = Pattern.CANON_EQ;
FLAG_LOOKUP['x'] = Pattern.COMMENTS;
FLAG_LOOKUP['d'] = Pattern.UNIX_LINES;
FLAG_LOOKUP['t'] = Pattern.LITERAL;
FLAG_LOOKUP['u'] = Pattern.UNICODE_CASE;
}
private @Nullable String key;
private List<Criteria> criteriaChain;
private LinkedHashMap<String, Object> criteria = new LinkedHashMap<String, Object>();
@@ -530,7 +517,7 @@ public class Criteria implements CriteriaDefinition {
Assert.notNull(regex, "Regex string must not be null!");
return Pattern.compile(regex, regexFlags(options));
return Pattern.compile(regex, RegexFlags.toRegexFlags(options));
}
/**
@@ -1099,47 +1086,6 @@ public class Criteria implements CriteriaDefinition {
|| (value instanceof GeoCommand && ((GeoCommand) value).getShape() instanceof GeoJson);
}
/**
* Lookup the MongoDB specific flags for a given regex option string.
*
* @param s the Regex option/flag to look up. Can be {@literal null}.
* @return zero if given {@link String} is {@literal null} or empty.
* @since 2.2
*/
private static int regexFlags(@Nullable String s) {
int flags = 0;
if (s == null) {
return flags;
}
for (final char f : s.toLowerCase().toCharArray()) {
flags |= regexFlag(f);
}
return flags;
}
/**
* Lookup the MongoDB specific flags for a given character.
*
* @param c the Regex option/flag to look up.
* @return
* @throws IllegalArgumentException for unknown flags
* @since 2.2
*/
private static int regexFlag(char c) {
int flag = FLAG_LOOKUP[c];
if (flag == 0) {
throw new IllegalArgumentException(String.format("Unrecognized flag [%c]", c));
}
return flag;
}
/**
* MongoDB specific <a href="https://docs.mongodb.com/manual/reference/operator/query-bitwise/">bitwise query
* operators</a> like {@code $bitsAllClear, $bitsAllSet,...} for usage with {@link Criteria#bits()} and {@link Query}.

View File

@@ -0,0 +1,116 @@
/*
* Copyright 2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.mongodb.util;
import java.util.regex.Pattern;
import org.springframework.lang.Nullable;
/**
* Utility to translate {@link Pattern#flags() regex flags} to MongoDB regex options and vice versa.
*
* @author Mark Paluch
* @since 3.3
*/
public abstract class RegexFlags {
private static final int[] FLAG_LOOKUP = new int[Character.MAX_VALUE];
static {
FLAG_LOOKUP['g'] = 256;
FLAG_LOOKUP['i'] = Pattern.CASE_INSENSITIVE;
FLAG_LOOKUP['m'] = Pattern.MULTILINE;
FLAG_LOOKUP['s'] = Pattern.DOTALL;
FLAG_LOOKUP['c'] = Pattern.CANON_EQ;
FLAG_LOOKUP['x'] = Pattern.COMMENTS;
FLAG_LOOKUP['d'] = Pattern.UNIX_LINES;
FLAG_LOOKUP['t'] = Pattern.LITERAL;
FLAG_LOOKUP['u'] = Pattern.UNICODE_CASE;
}
private RegexFlags() {
}
/**
* Lookup the MongoDB specific options from given {@link Pattern#flags() flags}.
*
* @param flags the Regex flags to look up.
* @return the options string. May be empty.
*/
public static String toRegexOptions(int flags) {
if (flags == 0) {
return "";
}
StringBuilder buf = new StringBuilder();
for (int i = 'a'; i < 'z'; i++) {
if (FLAG_LOOKUP[i] == 0) {
continue;
}
if ((flags & FLAG_LOOKUP[i]) > 0) {
buf.append((char) i);
}
}
return buf.toString();
}
/**
* Lookup the MongoDB specific flags for a given regex option string.
*
* @param s the Regex option/flag to look up. Can be {@literal null}.
* @return zero if given {@link String} is {@literal null} or empty.
* @since 2.2
*/
public static int toRegexFlags(@Nullable String s) {
int flags = 0;
if (s == null) {
return flags;
}
for (char f : s.toLowerCase().toCharArray()) {
flags |= toRegexFlag(f);
}
return flags;
}
/**
* Lookup the MongoDB specific flags for a given character.
*
* @param c the Regex option/flag to look up.
* @return
* @throws IllegalArgumentException for unknown flags
* @since 2.2
*/
public static int toRegexFlag(char c) {
int flag = FLAG_LOOKUP[c];
if (flag == 0) {
throw new IllegalArgumentException(String.format("Unrecognized flag [%c]", c));
}
return flag;
}
}

View File

@@ -32,6 +32,7 @@ import org.springframework.data.mongodb.core.Person;
* @author Thomas Darimont
* @author Oliver Gierke
* @author Christoph Strobl
* @author Divya Srivastava
*/
public class SpelExpressionTransformerUnitTests {
@@ -800,68 +801,68 @@ public class SpelExpressionTransformerUnitTests {
assertThat(transform("rtrim(field1, field2)"))
.isEqualTo("{ \"$rtrim\" : {\"input\" : \"$field1\", \"chars\" : \"$field2\" }}");
}
@Test // DATAMONGO-3725
public void shouldRenderRegexFindWithoutOptions() {
@Test // GH-3725
void shouldRenderRegexFindWithoutOptions() {
assertThat(transform("regexFind(field1,'e')"))
.isEqualTo(Document.parse("{ \"$regexFind\" : {\"input\" : \"$field1\" , \"regex\" : \"e\"}}"));
}
@Test // DATAMONGO-3725
public void shouldRenderRegexFindWithOptions() {
assertThat(transform("regexFind(field1,'e','i')"))
.isEqualTo(Document.parse("{ \"$regexFind\" : {\"input\" : \"$field1\" , \"regex\" : \"e\" , \"options\" : \"i\"}}"));
}
@Test // DATAMONGO-3725
public void shouldRenderRegexFindWithOptionsFromFieldReference() {
assertThat(transform("regexFind(field1,'e',field2)"))
.isEqualTo(Document.parse("{ \"$regexFind\" : {\"input\" : \"$field1\" , \"regex\" : \"e\" , \"options\" : \"$field2\"}}"));
}
@Test // DATAMONGO-3725
public void shouldRenderRegexFindAllWithoutOptions() {
assertThat(transform("regexFindAll(field1,'e')"))
.isEqualTo(Document.parse("{ \"$regexFindAll\" : {\"input\" : \"$field1\" , \"regex\" : \"e\"}}"));
}
@Test // DATAMONGO-3725
public void shouldRenderRegexFindAllWithOptions() {
assertThat(transform("regexFindAll(field1,'e','i')"))
.isEqualTo(Document.parse("{ \"$regexFindAll\" : {\"input\" : \"$field1\" , \"regex\" : \"e\" , \"options\" : \"i\"}}"));
}
@Test // DATAMONGO-3725
public void shouldRenderRegexFindAllWithOptionsFromFieldReference() {
assertThat(transform("regexFindAll(field1,'e',field2)"))
.isEqualTo(Document.parse("{ \"$regexFindAll\" : {\"input\" : \"$field1\" , \"regex\" : \"e\" , \"options\" : \"$field2\"}}"));
.isEqualTo("{ \"$regexFind\" : {\"input\" : \"$field1\" , \"regex\" : \"e\"}}");
}
@Test // DATAMONGO-3725
public void shouldRenderRegexMatchWithoutOptions() {
@Test // GH-3725
void shouldRenderRegexFindWithOptions() {
assertThat(transform("regexFind(field1,'e','i')"))
.isEqualTo("{ \"$regexFind\" : {\"input\" : \"$field1\" , \"regex\" : \"e\" , \"options\" : \"i\"}}");
}
@Test // GH-3725
void shouldRenderRegexFindWithOptionsFromFieldReference() {
assertThat(transform("regexFind(field1,'e',field2)"))
.isEqualTo("{ \"$regexFind\" : {\"input\" : \"$field1\" , \"regex\" : \"e\" , \"options\" : \"$field2\"}}");
}
@Test // GH-3725
void shouldRenderRegexFindAllWithoutOptions() {
assertThat(transform("regexFindAll(field1,'e')"))
.isEqualTo("{ \"$regexFindAll\" : {\"input\" : \"$field1\" , \"regex\" : \"e\"}}");
}
@Test // GH-3725
void shouldRenderRegexFindAllWithOptions() {
assertThat(transform("regexFindAll(field1,'e','i')"))
.isEqualTo("{ \"$regexFindAll\" : {\"input\" : \"$field1\" , \"regex\" : \"e\" , \"options\" : \"i\"}}");
}
@Test // GH-3725
void shouldRenderRegexFindAllWithOptionsFromFieldReference() {
assertThat(transform("regexFindAll(field1,'e',field2)"))
.isEqualTo("{ \"$regexFindAll\" : {\"input\" : \"$field1\" , \"regex\" : \"e\" , \"options\" : \"$field2\"}}");
}
@Test // GH-3725
void shouldRenderRegexMatchWithoutOptions() {
assertThat(transform("regexMatch(field1,'e')"))
.isEqualTo(Document.parse("{ \"$regexMatch\" : {\"input\" : \"$field1\" , \"regex\" : \"e\"}}"));
.isEqualTo("{ \"$regexMatch\" : {\"input\" : \"$field1\" , \"regex\" : \"e\"}}");
}
@Test // DATAMONGO-3725
public void shouldRenderRegexMatchWithOptions() {
@Test // GH-3725
void shouldRenderRegexMatchWithOptions() {
assertThat(transform("regexMatch(field1,'e','i')"))
.isEqualTo(Document.parse("{ \"$regexMatch\" : {\"input\" : \"$field1\" , \"regex\" : \"e\" , \"options\" : \"i\"}}"));
.isEqualTo("{ \"$regexMatch\" : {\"input\" : \"$field1\" , \"regex\" : \"e\" , \"options\" : \"i\"}}");
}
@Test // DATAMONGO-3725
public void shouldRenderRegexMatchWithOptionsFromFieldReference() {
@Test // GH-3725
void shouldRenderRegexMatchWithOptionsFromFieldReference() {
assertThat(transform("regexMatch(field1,'e',field2)"))
.isEqualTo(Document.parse("{ \"$regexMatch\" : {\"input\" : \"$field1\" , \"regex\" : \"e\" , \"options\" : \"$field2\"}}"));
.isEqualTo("{ \"$regexMatch\" : {\"input\" : \"$field1\" , \"regex\" : \"e\" , \"options\" : \"$field2\"}}");
}

View File

@@ -15,7 +15,9 @@
*/
package org.springframework.data.mongodb.core.aggregation;
import static org.assertj.core.api.Assertions.*;
import static org.springframework.data.mongodb.test.util.Assertions.*;
import java.util.regex.Pattern;
import org.bson.Document;
import org.junit.jupiter.api.Test;
@@ -25,230 +27,258 @@ import org.junit.jupiter.api.Test;
*
* @author Christoph Strobl
* @author Mark Paluch
* @author Divya Srivastava
* @currentRead Royal Assassin - Robin Hobb
*/
public class StringOperatorsUnitTests {
class StringOperatorsUnitTests {
static final String EXPRESSION_STRING = "{ \"$fitz\" : \"chivalry\" }";
static final Document EXPRESSION_DOC = Document.parse(EXPRESSION_STRING);
static final AggregationExpression EXPRESSION = context -> EXPRESSION_DOC;
private static final String EXPRESSION_STRING = "{ \"$fitz\" : \"chivalry\" }";
private static final Document EXPRESSION_DOC = Document.parse(EXPRESSION_STRING);
private static final AggregationExpression EXPRESSION = context -> EXPRESSION_DOC;
@Test // DATAMONGO-2049
public void shouldRenderTrim() {
void shouldRenderTrim() {
assertThat(StringOperators.valueOf("shrewd").trim().toDocument(Aggregation.DEFAULT_CONTEXT))
.isEqualTo(Document.parse("{ $trim: { \"input\" : \"$shrewd\" } } "));
.isEqualTo("{ $trim: { \"input\" : \"$shrewd\" } } ");
}
@Test // DATAMONGO-2049
public void shouldRenderTrimForExpression() {
void shouldRenderTrimForExpression() {
assertThat(StringOperators.valueOf(EXPRESSION).trim().toDocument(Aggregation.DEFAULT_CONTEXT))
.isEqualTo(Document.parse("{ $trim: { \"input\" : " + EXPRESSION_STRING + " } } "));
.isEqualTo("{ $trim: { \"input\" : " + EXPRESSION_STRING + " } } ");
}
@Test // DATAMONGO-2049
public void shouldRenderTrimWithChars() {
void shouldRenderTrimWithChars() {
assertThat(StringOperators.valueOf("shrewd").trim("sh").toDocument(Aggregation.DEFAULT_CONTEXT))
.isEqualTo(Document.parse("{ $trim: { \"input\" : \"$shrewd\", \"chars\" : \"sh\" } } "));
.isEqualTo("{ $trim: { \"input\" : \"$shrewd\", \"chars\" : \"sh\" } } ");
}
@Test // DATAMONGO-2049
public void shouldRenderTrimWithCharsExpression() {
void shouldRenderTrimWithCharsExpression() {
assertThat(StringOperators.valueOf("shrewd").trim(EXPRESSION).toDocument(Aggregation.DEFAULT_CONTEXT))
.isEqualTo(Document.parse("{ $trim: { \"input\" : \"$shrewd\", \"chars\" : " + EXPRESSION_STRING + " } } "));
.isEqualTo("{ $trim: { \"input\" : \"$shrewd\", \"chars\" : " + EXPRESSION_STRING + " } } ");
}
@Test // DATAMONGO-2049
public void shouldRenderTrimLeft() {
void shouldRenderTrimLeft() {
assertThat(StringOperators.valueOf("shrewd").trim().left().toDocument(Aggregation.DEFAULT_CONTEXT))
.isEqualTo(Document.parse("{ $ltrim: { \"input\" : \"$shrewd\" } } "));
.isEqualTo("{ $ltrim: { \"input\" : \"$shrewd\" } } ");
}
@Test // DATAMONGO-2049
public void shouldRenderTrimLeftWithChars() {
void shouldRenderTrimLeftWithChars() {
assertThat(StringOperators.valueOf("shrewd").trim("sh").left().toDocument(Aggregation.DEFAULT_CONTEXT))
.isEqualTo(Document.parse("{ $ltrim: { \"input\" : \"$shrewd\", \"chars\" : \"sh\" } } "));
.isEqualTo("{ $ltrim: { \"input\" : \"$shrewd\", \"chars\" : \"sh\" } } ");
}
@Test // DATAMONGO-2049
public void shouldRenderTrimRight() {
void shouldRenderTrimRight() {
assertThat(StringOperators.valueOf("shrewd").trim().right().toDocument(Aggregation.DEFAULT_CONTEXT))
.isEqualTo(Document.parse("{ $rtrim: { \"input\" : \"$shrewd\" } } "));
.isEqualTo("{ $rtrim: { \"input\" : \"$shrewd\" } } ");
}
@Test // DATAMONGO-2049
public void shouldRenderTrimRightWithChars() {
void shouldRenderTrimRightWithChars() {
assertThat(StringOperators.valueOf("shrewd").trim("sh").right().toDocument(Aggregation.DEFAULT_CONTEXT))
.isEqualTo(Document.parse("{ $rtrim: { \"input\" : \"$shrewd\", \"chars\" : \"sh\" } } "));
.isEqualTo("{ $rtrim: { \"input\" : \"$shrewd\", \"chars\" : \"sh\" } } ");
}
@Test // DATAMONGO-2049
public void shouldRenderLTrim() {
void shouldRenderLTrim() {
assertThat(StringOperators.valueOf("shrewd").ltrim().toDocument(Aggregation.DEFAULT_CONTEXT))
.isEqualTo(Document.parse("{ $ltrim: { \"input\" : \"$shrewd\" } } "));
.isEqualTo("{ $ltrim: { \"input\" : \"$shrewd\" } } ");
}
@Test // DATAMONGO-2049
public void shouldRenderLTrimForExpression() {
void shouldRenderLTrimForExpression() {
assertThat(StringOperators.valueOf(EXPRESSION).ltrim().toDocument(Aggregation.DEFAULT_CONTEXT))
.isEqualTo(Document.parse("{ $ltrim: { \"input\" : " + EXPRESSION_STRING + " } } "));
.isEqualTo("{ $ltrim: { \"input\" : " + EXPRESSION_STRING + " } } ");
}
@Test // DATAMONGO-2049
public void shouldRenderLTrimWithChars() {
void shouldRenderLTrimWithChars() {
assertThat(StringOperators.valueOf("shrewd").ltrim("sh").toDocument(Aggregation.DEFAULT_CONTEXT))
.isEqualTo(Document.parse("{ $ltrim: { \"input\" : \"$shrewd\", \"chars\" : \"sh\" } } "));
.isEqualTo("{ $ltrim: { \"input\" : \"$shrewd\", \"chars\" : \"sh\" } } ");
}
@Test // DATAMONGO-2049
public void shouldRenderLTrimWithCharsExpression() {
void shouldRenderLTrimWithCharsExpression() {
assertThat(StringOperators.valueOf("shrewd").ltrim(EXPRESSION).toDocument(Aggregation.DEFAULT_CONTEXT))
.isEqualTo(Document.parse("{ $ltrim: { \"input\" : \"$shrewd\", \"chars\" : " + EXPRESSION_STRING + " } } "));
.isEqualTo("{ $ltrim: { \"input\" : \"$shrewd\", \"chars\" : " + EXPRESSION_STRING + " } } ");
}
@Test // DATAMONGO-2049
public void shouldRenderRTrim() {
void shouldRenderRTrim() {
assertThat(StringOperators.valueOf("shrewd").rtrim().toDocument(Aggregation.DEFAULT_CONTEXT))
.isEqualTo(Document.parse("{ $rtrim: { \"input\" : \"$shrewd\" } } "));
.isEqualTo("{ $rtrim: { \"input\" : \"$shrewd\" } } ");
}
@Test // DATAMONGO-2049
public void shouldRenderRTrimForExpression() {
void shouldRenderRTrimForExpression() {
assertThat(StringOperators.valueOf(EXPRESSION).rtrim().toDocument(Aggregation.DEFAULT_CONTEXT))
.isEqualTo(Document.parse("{ $rtrim: { \"input\" : " + EXPRESSION_STRING + " } } "));
.isEqualTo("{ $rtrim: { \"input\" : " + EXPRESSION_STRING + " } } ");
}
@Test // DATAMONGO-2049
public void shouldRenderRTrimWithChars() {
void shouldRenderRTrimWithChars() {
assertThat(StringOperators.valueOf("shrewd").rtrim("sh").toDocument(Aggregation.DEFAULT_CONTEXT))
.isEqualTo(Document.parse("{ $rtrim: { \"input\" : \"$shrewd\", \"chars\" : \"sh\" } } "));
.isEqualTo("{ $rtrim: { \"input\" : \"$shrewd\", \"chars\" : \"sh\" } } ");
}
@Test // DATAMONGO-2049
public void shouldRenderRTrimWithCharsExpression() {
void shouldRenderRTrimWithCharsExpression() {
assertThat(StringOperators.valueOf("shrewd").rtrim(EXPRESSION).toDocument(Aggregation.DEFAULT_CONTEXT))
.isEqualTo(Document.parse("{ $rtrim: { \"input\" : \"$shrewd\", \"chars\" : " + EXPRESSION_STRING + " } } "));
.isEqualTo("{ $rtrim: { \"input\" : \"$shrewd\", \"chars\" : " + EXPRESSION_STRING + " } } ");
}
@Test // DATAMONGO - 3725
public void shouldRenderRegexFindAll() {
@Test // GH-3725
void shouldRenderRegexFindAll() {
assertThat(StringOperators.valueOf("shrewd").regexFindAll("e").toDocument(Aggregation.DEFAULT_CONTEXT))
.isEqualTo(Document.parse("{ $regexFindAll: { \"input\" : \"$shrewd\" , \"regex\" : \"e\" } }"));
.isEqualTo("{ $regexFindAll: { \"input\" : \"$shrewd\" , \"regex\" : \"e\" } }");
}
@Test // DATAMONGO - 3725
public void shouldRenderRegexFindAllForExpression() {
@Test // GH-3725
void shouldRenderRegexFindAllForExpression() {
assertThat(StringOperators.valueOf(EXPRESSION).regexFindAll("e").toDocument(Aggregation.DEFAULT_CONTEXT))
.isEqualTo(Document.parse("{ $regexFindAll: { \"input\" : " + EXPRESSION_STRING + " , \"regex\" : \"e\" } } "));
.isEqualTo("{ $regexFindAll: { \"input\" : " + EXPRESSION_STRING + " , \"regex\" : \"e\" } } ");
}
@Test // DATAMONGO - 3725
public void shouldRenderRegexFindAllForRegexExpression() {
@Test // GH-3725
void shouldRenderRegexFindAllForRegexExpression() {
assertThat(StringOperators.valueOf("shrewd").regexFindAll(EXPRESSION).toDocument(Aggregation.DEFAULT_CONTEXT))
.isEqualTo(Document.parse("{ $regexFindAll: { \"input\" : \"$shrewd\" , \"regex\" : " + EXPRESSION_STRING + " } } "));
.isEqualTo("{ $regexFindAll: { \"input\" : \"$shrewd\" , \"regex\" : " + EXPRESSION_STRING + " } } ");
}
@Test // DATAMONGO - 3725
public void shouldRenderRegexFindAllWithOptions() {
@Test // GH-3725
void shouldRenderRegexFindAllWithPattern() {
assertThat(StringOperators.valueOf("shrewd")
.regexFindAll(
Pattern.compile("foo", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL | Pattern.COMMENTS))
.toDocument(Aggregation.DEFAULT_CONTEXT))
.isEqualTo("{ $regexFindAll: { \"input\" : \"$shrewd\", \"regex\" : \"foo\" , \"options\" : \"imsx\" } } ");
}
@Test // GH-3725
void shouldRenderRegexFindAllWithOptions() {
assertThat(StringOperators.valueOf("shrewd").regexFindAll("e").options("i").toDocument(Aggregation.DEFAULT_CONTEXT))
.isEqualTo(Document.parse("{ $regexFindAll: { \"input\" : \"$shrewd\", \"regex\" : \"e\" , \"options\" : \"i\" } } "));
.isEqualTo("{ $regexFindAll: { \"input\" : \"$shrewd\", \"regex\" : \"e\" , \"options\" : \"i\" } } ");
}
@Test // DATAMONGO - 3725
public void shouldRenderRegexFindAllWithOptionsExpression() {
@Test // GH-3725
void shouldRenderRegexFindAllWithOptionsExpression() {
assertThat(StringOperators.valueOf("shrewd").regexFindAll("e").optionsOf(EXPRESSION).toDocument(Aggregation.DEFAULT_CONTEXT))
.isEqualTo(Document.parse("{ $regexFindAll: { \"input\" : \"$shrewd\", \"regex\" : \"e\" , \"options\" : " + EXPRESSION_STRING + " } } "));
.isEqualTo("{ $regexFindAll: { \"input\" : \"$shrewd\", \"regex\" : \"e\" , \"options\" : " + EXPRESSION_STRING
+ " } } ");
}
@Test // DATAMONGO - 3725
public void shouldRenderRegexMatch() {
@Test // GH-3725
void shouldRenderRegexMatch() {
assertThat(StringOperators.valueOf("shrewd").regexMatch("e").toDocument(Aggregation.DEFAULT_CONTEXT))
.isEqualTo(Document.parse("{ $regexMatch: { \"input\" : \"$shrewd\" , \"regex\" : \"e\" } }"));
.isEqualTo("{ $regexMatch: { \"input\" : \"$shrewd\" , \"regex\" : \"e\" } }");
}
@Test // DATAMONGO - 3725
public void shouldRenderRegexMatchForExpression() {
@Test // GH-3725
void shouldRenderRegexMatchForExpression() {
assertThat(StringOperators.valueOf(EXPRESSION).regexMatch("e").toDocument(Aggregation.DEFAULT_CONTEXT))
.isEqualTo(Document.parse("{ $regexMatch: { \"input\" : " + EXPRESSION_STRING + " , \"regex\" : \"e\" } } "));
.isEqualTo("{ $regexMatch: { \"input\" : " + EXPRESSION_STRING + " , \"regex\" : \"e\" } } ");
}
@Test // DATAMONGO - 3725
public void shouldRenderRegexMatchForRegexExpression() {
@Test // GH-3725
void shouldRenderRegexMatchForRegexExpression() {
assertThat(StringOperators.valueOf("shrewd").regexMatch(EXPRESSION).toDocument(Aggregation.DEFAULT_CONTEXT))
.isEqualTo(Document.parse("{ $regexMatch: { \"input\" : \"$shrewd\" , \"regex\" : " + EXPRESSION_STRING + " } } "));
.isEqualTo("{ $regexMatch: { \"input\" : \"$shrewd\" , \"regex\" : " + EXPRESSION_STRING + " } } ");
}
@Test // DATAMONGO - 3725
public void shouldRenderRegexMatchWithOptions() {
@Test // GH-3725
void shouldRenderRegexMatchForPattern() {
assertThat(StringOperators.valueOf("shrewd").regexMatch(Pattern.compile("foo", Pattern.CASE_INSENSITIVE))
.toDocument(Aggregation.DEFAULT_CONTEXT))
.isEqualTo("{ $regexMatch: { \"input\" : \"$shrewd\" , \"regex\" : \"foo\", \"options\" : \"i\"} } ");
}
@Test // GH-3725
void shouldRenderRegexMatchWithOptions() {
assertThat(StringOperators.valueOf("shrewd").regexMatch("e").options("i").toDocument(Aggregation.DEFAULT_CONTEXT))
.isEqualTo(Document.parse("{ $regexMatch: { \"input\" : \"$shrewd\", \"regex\" : \"e\" , \"options\" : \"i\" } } "));
.isEqualTo("{ $regexMatch: { \"input\" : \"$shrewd\", \"regex\" : \"e\" , \"options\" : \"i\" } } ");
}
@Test // DATAMONGO - 3725
public void shouldRenderRegexMatchWithOptionsExpression() {
@Test // GH-3725
void shouldRenderRegexMatchWithOptionsExpression() {
assertThat(StringOperators.valueOf("shrewd").regexMatch("e").optionsOf(EXPRESSION).toDocument(Aggregation.DEFAULT_CONTEXT))
.isEqualTo(Document.parse("{ $regexMatch: { \"input\" : \"$shrewd\", \"regex\" : \"e\" , \"options\" : " + EXPRESSION_STRING + " } } "));
.isEqualTo("{ $regexMatch: { \"input\" : \"$shrewd\", \"regex\" : \"e\" , \"options\" : " + EXPRESSION_STRING
+ " } } ");
}
@Test // DATAMONGO - 3725
public void shouldRenderRegexFind() {
@Test // GH-3725
void shouldRenderRegexFind() {
assertThat(StringOperators.valueOf("shrewd").regexFind("e").toDocument(Aggregation.DEFAULT_CONTEXT))
.isEqualTo(Document.parse("{ $regexFind: { \"input\" : \"$shrewd\" , \"regex\" : \"e\" } }"));
.isEqualTo("{ $regexFind: { \"input\" : \"$shrewd\" , \"regex\" : \"e\" } }");
}
@Test // DATAMONGO - 3725
public void shouldRenderRegexFindForExpression() {
@Test // GH-3725
void shouldRenderRegexFindForExpression() {
assertThat(StringOperators.valueOf(EXPRESSION).regexFind("e").toDocument(Aggregation.DEFAULT_CONTEXT))
.isEqualTo(Document.parse("{ $regexFind: { \"input\" : " + EXPRESSION_STRING + " , \"regex\" : \"e\" } } "));
.isEqualTo("{ $regexFind: { \"input\" : " + EXPRESSION_STRING + " , \"regex\" : \"e\" } } ");
}
@Test // DATAMONGO - 3725
public void shouldRenderRegexFindForRegexExpression() {
@Test // GH-3725
void shouldRenderRegexFindForRegexExpression() {
assertThat(StringOperators.valueOf("shrewd").regexFind(EXPRESSION).toDocument(Aggregation.DEFAULT_CONTEXT))
.isEqualTo(Document.parse("{ $regexFind: { \"input\" : \"$shrewd\" , \"regex\" : " + EXPRESSION_STRING + " } } "));
.isEqualTo("{ $regexFind: { \"input\" : \"$shrewd\" , \"regex\" : " + EXPRESSION_STRING + " } } ");
}
@Test // DATAMONGO - 3725
public void shouldRenderRegexFindWithOptions() {
@Test // GH-3725
void shouldRenderRegexFindForPattern() {
assertThat(StringOperators.valueOf("shrewd").regexFind(Pattern.compile("foo", Pattern.MULTILINE))
.toDocument(Aggregation.DEFAULT_CONTEXT))
.isEqualTo("{ $regexFind: { \"input\" : \"$shrewd\" , \"regex\" : \"foo\", \"options\" : \"m\"} } ");
}
@Test // GH-3725
void shouldRenderRegexFindWithOptions() {
assertThat(StringOperators.valueOf("shrewd").regexFind("e").options("i").toDocument(Aggregation.DEFAULT_CONTEXT))
.isEqualTo(Document.parse("{ $regexFind: { \"input\" : \"$shrewd\", \"regex\" : \"e\" , \"options\" : \"i\" } } "));
.isEqualTo("{ $regexFind: { \"input\" : \"$shrewd\", \"regex\" : \"e\" , \"options\" : \"i\" } } ");
}
@Test // DATAMONGO - 3725
public void shouldRenderRegexFindWithOptionsExpression() {
@Test // GH-3725
void shouldRenderRegexFindWithOptionsExpression() {
assertThat(StringOperators.valueOf("shrewd").regexFind("e").optionsOf(EXPRESSION).toDocument(Aggregation.DEFAULT_CONTEXT))
.isEqualTo(Document.parse("{ $regexFind: { \"input\" : \"$shrewd\", \"regex\" : \"e\" , \"options\" : " + EXPRESSION_STRING + " } } "));
.isEqualTo("{ $regexFind: { \"input\" : \"$shrewd\", \"regex\" : \"e\" , \"options\" : " + EXPRESSION_STRING
+ " } } ");
}
}

View File

@@ -88,7 +88,7 @@ At the time of this writing, we provide support for the following Aggregation Op
| `abs`, `add` (+++*+++ via `plus`), `ceil`, `cos`, `cosh`, `derivative`, `divide`, `exp`, `floor`, `integral`, `ln`, `log`, `log10`, `mod`, `multiply`, `pow`, `round`, `sqrt`, `subtract` (+++*+++ via `minus`), `sin`, `sinh`, `tan`, `tanh`, `trunc`
| String Aggregation Operators
| `concat`, `substr`, `toLower`, `toUpper`, `strcasecmp`, `indexOfBytes`, `indexOfCP`, `split`, `strLenBytes`, `strLenCP`, `substrCP`, `trim`, `ltrim`, `rtim`
| `concat`, `substr`, `toLower`, `toUpper`, `strcasecmp`, `indexOfBytes`, `indexOfCP`, `regexFind`, `regexFindAll`, `regexMatch`, `split`, `strLenBytes`, `strLenCP`, `substrCP`, `trim`, `ltrim`, `rtim`
| Comparison Aggregation Operators
| `eq` (+++*+++ via `is`), `gt`, `gte`, `lt`, `lte`, `ne`