Skip to content
Merged
Show file tree
Hide file tree
Changes from 42 commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
7f5ae1d
Support match_phrase in AST expressions
Apr 22, 2022
35da9e9
Support match_phrase in PPL syntax
Apr 26, 2022
cee993f
Added MATCH_QUERY to the list of supported functions in SQL parser.
Yury-Fridlyand Apr 26, 2022
dac5a7c
Support slop parameter for relevancy functions
Apr 26, 2022
5e88bc9
Typo fix for previous commit. Expanded list of MATCH_* function argum…
Yury-Fridlyand Apr 26, 2022
0e5a9a9
Integration tests for match_test in PPL
Apr 26, 2022
b508fc5
Support slop option
Apr 26, 2022
ce2142e
Tests to verify that PPL parser supports match_phrase
Apr 26, 2022
21ed960
Refactor and style fixes
Apr 26, 2022
c705d35
Refactor and fix style in OpenSearchFunctions.java
Apr 26, 2022
60e03b9
Style fixes for OpenSearchFunctionsTest.java
Apr 26, 2022
a2a1b21
Add tests for `MATCH` and `MATCH_PHRASE` functions.
Yury-Fridlyand Apr 26, 2022
76bdde0
Typo fix.
Yury-Fridlyand Apr 26, 2022
4a65a55
Fix style and minor refactor in PPLSyntaxParserTest.java
Apr 26, 2022
f6d1038
Minor test improvements
Yury-Fridlyand Apr 26, 2022
126651c
Parameterized test for match_phrase parsing
Apr 28, 2022
db81145
Merge pull request #44 from Bit-Quill/dev-match_phrase-#185-sql-synta…
MaxKsyunz Apr 28, 2022
b4f0b8a
Merge branch 'dev-match_phrase-#185' of https://github.com/Bit-Quill/…
Apr 28, 2022
b4fc092
Add `MATCH_PHRASE` function to the function repository.
Yury-Fridlyand Apr 27, 2022
0b930c8
Finally added `MATCH_PHASE` query support to `FilterQueryBuilder`.
Yury-Fridlyand Apr 28, 2022
89fa0ed
Typo fix + EOL fix
Yury-Fridlyand Apr 28, 2022
6aedf4f
Typo fix
Yury-Fridlyand Apr 29, 2022
61f2155
Adding tests for `FilterQueryBuilder` for `MATCH_PHRASE`. Some tests …
Yury-Fridlyand Apr 29, 2022
958cffb
Address PR feedback.
Yury-Fridlyand May 2, 2022
dd9776a
Add documentation for `MATCH_PHRASE` function.
Yury-Fridlyand May 2, 2022
05e5952
Remove duplicate definition of match_phrase in DSL.java
May 3, 2022
5bf470c
Generate supported signatures for match and match_phrases
May 3, 2022
dda36f9
Simplify match_phrase test.
May 3, 2022
3a1d9b1
Some sample queries with match_phrase for parser test
May 3, 2022
81ce4c7
Update PPL documentation.
May 3, 2022
63009a0
Update query samples in docs. Add a new table to doctest to match the…
Yury-Fridlyand May 4, 2022
c0bf42b
Recover `FUZZY_REWRITE` - was deleted by mistake.
Yury-Fridlyand May 4, 2022
b39ea26
Add missing file for `63009a05`.
Yury-Fridlyand May 4, 2022
87c42a7
Use constant seed to produce repeatable samples
May 4, 2022
29338de
Enable integration tests for match_phrase in PPL
May 4, 2022
f86d4ca
Fix code style.
Yury-Fridlyand May 4, 2022
c42088a
Make generateAndTestQueries() product consistent results.
May 4, 2022
a52e9f5
use generateQueries to generate samples for match_phrase
May 4, 2022
957b46e
Fix finction signature list. Typo fix for `5bf470c7`.
Yury-Fridlyand May 4, 2022
ed98a49
Fix code styling.
Yury-Fridlyand May 4, 2022
5a31fbf
Minor style changes.
May 6, 2022
4ca8a15
Add newline at the end of file.
May 6, 2022
d3bd5df
Simplify MatchPhraseQuery and add unit tests.
May 9, 2022
a15dacc
Remove unused imports.
May 9, 2022
7c3ff01
Change data used by WhereCommandIT
May 9, 2022
8d7039a
Style update for OpenSearchFunctions
May 9, 2022
87b6038
100% test coverage for MatchPhraseQuery
May 9, 2022
d2a45cc
Fix imports in WhereCommandIT
May 10, 2022
e6f7e2f
Move final variables to class constants in OpenSearchFunctions
May 10, 2022
0006dd3
Fix checkstyle failure.
May 10, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions core/src/main/java/org/opensearch/sql/expression/DSL.java
Original file line number Diff line number Diff line change
Expand Up @@ -651,7 +651,16 @@ public FunctionExpression castDatetime(Expression value) {
}

public FunctionExpression match(Expression... args) {
return (FunctionExpression) repository
.compile(BuiltinFunctionName.MATCH.getName(), Arrays.asList(args.clone()));
return compile(BuiltinFunctionName.MATCH, args);
}

public FunctionExpression match_phrase(Expression... args) {
return compile(BuiltinFunctionName.MATCH_PHRASE, args);
}

private FunctionExpression compile(BuiltinFunctionName bfn, Expression... args) {
return (FunctionExpression) repository.compile(bfn.getName(), Arrays.asList(args.clone()));
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ public enum BuiltinFunctionName {
* Relevance Function.
*/
MATCH(FunctionName.of("match")),
MATCH_PHRASE(FunctionName.of("match_phrase")),

/**
* Legacy Relevance Function.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@

import static org.opensearch.sql.data.type.ExprCoreType.STRING;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import lombok.ToString;
import lombok.experimental.UtilityClass;
import org.opensearch.sql.data.model.ExprValue;
import org.opensearch.sql.data.type.ExprCoreType;
Expand All @@ -25,54 +25,38 @@
public class OpenSearchFunctions {
public void register(BuiltinFunctionRepository repository) {
repository.register(match());
repository.register(match_phrase());
}

private static FunctionResolver match() {
FunctionName funcName = BuiltinFunctionName.MATCH.getName();
// At least field and query parameters
// At most field, query, and all optional parameters
return getFunctionResolver(funcName, 2, 14);
Comment thread
MaxKsyunz marked this conversation as resolved.
Outdated
}

private static FunctionResolver match_phrase() {
FunctionName funcName = BuiltinFunctionName.MATCH_PHRASE.getName();
// At least field and query parameters
// At most field, query, and all optional parameters
return getFunctionResolver(funcName, 2, 5);
Comment thread
MaxKsyunz marked this conversation as resolved.
Outdated
}

private static FunctionResolver getFunctionResolver(
FunctionName funcName, int minNumParameters, int maxNumParameters) {
return new FunctionResolver(funcName,
ImmutableMap.<FunctionSignature, FunctionBuilder>builder()
.put(new FunctionSignature(funcName, ImmutableList.of(STRING, STRING)),
args -> new OpenSearchFunction(funcName, args))
.put(new FunctionSignature(funcName, ImmutableList.of(STRING, STRING, STRING)),
args -> new OpenSearchFunction(funcName, args))
.put(new FunctionSignature(funcName, ImmutableList.of(STRING, STRING, STRING, STRING)),
args -> new OpenSearchFunction(funcName, args))
.put(new FunctionSignature(funcName, ImmutableList
.of(STRING, STRING, STRING, STRING, STRING)),
args -> new OpenSearchFunction(funcName, args))
.put(new FunctionSignature(funcName, ImmutableList
.of(STRING, STRING, STRING, STRING, STRING, STRING)),
args -> new OpenSearchFunction(funcName, args))
.put(new FunctionSignature(funcName, ImmutableList
.of(STRING, STRING, STRING, STRING, STRING, STRING, STRING)),
args -> new OpenSearchFunction(funcName, args))
.put(new FunctionSignature(funcName, ImmutableList
.of(STRING, STRING, STRING, STRING, STRING, STRING, STRING, STRING)),
args -> new OpenSearchFunction(funcName, args))
.put(new FunctionSignature(funcName, ImmutableList
.of(STRING, STRING, STRING, STRING, STRING, STRING, STRING, STRING, STRING)),
args -> new OpenSearchFunction(funcName, args))
.put(new FunctionSignature(funcName, ImmutableList
.of(STRING, STRING, STRING, STRING, STRING, STRING, STRING, STRING, STRING,
STRING)),
args -> new OpenSearchFunction(funcName, args))
.put(new FunctionSignature(funcName, ImmutableList
.of(STRING, STRING, STRING, STRING, STRING, STRING, STRING, STRING, STRING,
STRING, STRING)),
args -> new OpenSearchFunction(funcName, args))
.put(new FunctionSignature(funcName, ImmutableList
.of(STRING, STRING, STRING, STRING, STRING, STRING, STRING, STRING, STRING,
STRING, STRING, STRING)),
args -> new OpenSearchFunction(funcName, args))
.put(new FunctionSignature(funcName, ImmutableList
.of(STRING, STRING, STRING, STRING, STRING, STRING, STRING, STRING, STRING,
STRING, STRING, STRING, STRING)),
args -> new OpenSearchFunction(funcName, args))
.put(new FunctionSignature(funcName, ImmutableList
.of(STRING, STRING, STRING, STRING, STRING, STRING, STRING, STRING, STRING,
STRING, STRING, STRING, STRING, STRING)),
args -> new OpenSearchFunction(funcName, args))
.build());
getSignatureMap(funcName, minNumParameters, maxNumParameters));
}

private static Map<FunctionSignature, FunctionBuilder> getSignatureMap(
FunctionName funcName, int minNumParameters, int maxNumParameters) {
FunctionBuilder buildFunction = args -> new OpenSearchFunction(funcName, args);
var signatureMapBuilder = ImmutableMap.<FunctionSignature, FunctionBuilder>builder();
for (int numParameters = minNumParameters; numParameters <= maxNumParameters; numParameters++) {
List<ExprType> args = Collections.nCopies(numParameters, STRING);
signatureMapBuilder.put(new FunctionSignature(funcName, args), buildFunction);
}
return signatureMapBuilder.build();
}

private static class OpenSearchFunction extends FunctionExpression {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,15 @@
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.opensearch.sql.data.type.ExprCoreType.BOOLEAN;

import java.util.List;
import org.junit.jupiter.api.Test;
import org.opensearch.sql.expression.DSL;
import org.opensearch.sql.expression.ExpressionTestBase;
import org.opensearch.sql.expression.FunctionExpression;
import org.opensearch.sql.expression.NamedArgumentExpression;



public class OpenSearchFunctionsTest extends ExpressionTestBase {
private final NamedArgumentExpression field = new NamedArgumentExpression(
"field", DSL.literal("message"));
Expand All @@ -40,10 +43,14 @@ public class OpenSearchFunctionsTest extends ExpressionTestBase {
"operator", DSL.literal("OR"));
private final NamedArgumentExpression minimumShouldMatch = new NamedArgumentExpression(
"minimum_should_match", DSL.literal("1"));
private final NamedArgumentExpression zeroTermsQuery = new NamedArgumentExpression(
"zero_terms_query", DSL.literal("ALL"));
private final NamedArgumentExpression zeroTermsQueryAll = new NamedArgumentExpression(
"zero_terms_query", DSL.literal("ALL"));
private final NamedArgumentExpression zeroTermsQueryNone = new NamedArgumentExpression(
"zero_terms_query", DSL.literal("None"));
private final NamedArgumentExpression boost = new NamedArgumentExpression(
"boost", DSL.literal("2.0"));
private final NamedArgumentExpression slop = new NamedArgumentExpression(
"slop", DSL.literal("3"));

@Test
void match() {
Expand Down Expand Up @@ -98,16 +105,34 @@ void match() {

expr = dsl.match(
field, query, analyzer, autoGenerateSynonymsPhrase, fuzziness, maxExpansions, prefixLength,
fuzzyTranspositions, fuzzyRewrite, lenient, operator, minimumShouldMatch, zeroTermsQuery);
fuzzyTranspositions, fuzzyRewrite, lenient, operator, minimumShouldMatch,
zeroTermsQueryAll);
assertEquals(BOOLEAN, expr.type());

expr = dsl.match(
field, query, analyzer, autoGenerateSynonymsPhrase, fuzziness, maxExpansions, prefixLength,
fuzzyTranspositions, fuzzyRewrite, lenient, operator, minimumShouldMatch, zeroTermsQuery,
fuzzyTranspositions, fuzzyRewrite, lenient, operator, minimumShouldMatch, zeroTermsQueryAll,
boost);
assertEquals(BOOLEAN, expr.type());
}

@Test
void match_phrase() {
for (FunctionExpression expr : match_phrase_dsl_expressions()) {
assertEquals(BOOLEAN, expr.type());
}
}


List<FunctionExpression> match_phrase_dsl_expressions() {
return List.of(
dsl.match_phrase(field, query),
dsl.match_phrase(field, query, analyzer),
dsl.match_phrase(field, query, analyzer, zeroTermsQueryAll),
dsl.match_phrase(field, query, analyzer, zeroTermsQueryNone, slop)
Comment thread
Yury-Fridlyand marked this conversation as resolved.
);
}

@Test
void match_in_memory() {
FunctionExpression expr = dsl.match(field, query);
Expand Down
38 changes: 38 additions & 0 deletions docs/user/dql/functions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2195,3 +2195,41 @@ Another example to show how to set custom values for the optional parameters::
| Bond |
+------------+

MATCH_PHRASE
-----

Description
>>>>>>>>>>>

``match_phrase(field_expression, query_expression[, option=<option_value>]*)``

The match_phrase function maps to the match_phrase query used in search engine, to return the documents that match a provided text with a given field. Available parameters include:

- analyzer
- slop
- zero_terms_query

Example with only ``field`` and ``query`` expressions, and all other parameters are set default values::

os> SELECT author, title FROM books WHERE match_phrase(author, 'Alexander Milne');
fetched rows / total rows = 2/2
+----------------------+--------------------------+
| author | title |
|----------------------+--------------------------|
| Alan Alexander Milne | The House at Pooh Corner |
| Alan Alexander Milne | Winnie-the-Pooh |
+----------------------+--------------------------+



Another example to show how to set custom values for the optional parameters::

os> SELECT author, title FROM books WHERE match_phrase(author, 'Alan Milne', slop = 2);
fetched rows / total rows = 2/2
+----------------------+--------------------------+
| author | title |
|----------------------+--------------------------|
| Alan Alexander Milne | The House at Pooh Corner |
| Alan Alexander Milne | Winnie-the-Pooh |
+----------------------+--------------------------+

38 changes: 38 additions & 0 deletions docs/user/ppl/functions/relevance.rst
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,44 @@ Another example to show how to set custom values for the optional parameters::
| Bond |
+------------+

MATCH_PHRASE
-----

Description
>>>>>>>>>>>

``match_phrase(field_expression, query_expression[, option=<option_value>]*)``

The match_phrase function maps to the match_phrase query used in search engine, to return the documents that match a provided text with a given field. Available parameters include:

- analyzer
- slop
- zero_terms_query

Example with only ``field`` and ``query`` expressions, and all other parameters are set default values::

os> source=books | where match_phrase(author, 'Alexander Milne') | fields author, title
fetched rows / total rows = 2/2
+----------------------+--------------------------+
| author | title |
|----------------------+--------------------------|
| Alan Alexander Milne | The House at Pooh Corner |
| Alan Alexander Milne | Winnie-the-Pooh |
+----------------------+--------------------------+



Another example to show how to set custom values for the optional parameters::

os> source=books | where match_phrase(author, 'Alan Milne', slop = 2) | fields author, title
fetched rows / total rows = 2/2
+----------------------+--------------------------+
| author | title |
|----------------------+--------------------------|
| Alan Alexander Milne | The House at Pooh Corner |
| Alan Alexander Milne | Winnie-the-Pooh |
+----------------------+--------------------------+

Limitations
>>>>>>>>>>>

Expand Down
2 changes: 2 additions & 0 deletions doctest/test_data/books.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
{"id": 1, "author": "Alan Alexander Milne", "title": "The House at Pooh Corner"}
{"id": 2, "author": "Alan Alexander Milne", "title": "Winnie-the-Pooh"}
4 changes: 3 additions & 1 deletion doctest/test_docs.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
PEOPLE = "people"
ACCOUNT2 = "account2"
NYC_TAXI = "nyc_taxi"
BOOKS = "books"


class DocTestConnection(OpenSearchConnection):
Expand Down Expand Up @@ -88,6 +89,7 @@ def set_up_test_indices(test):
load_file("people.json", index_name=PEOPLE)
load_file("account2.json", index_name=ACCOUNT2)
load_file("nyc_taxi.json", index_name=NYC_TAXI)
load_file("books.json", index_name=BOOKS)


def load_file(filename, index_name):
Expand Down Expand Up @@ -116,7 +118,7 @@ def set_up(test):

def tear_down(test):
# drop leftover tables after each test
test_data_client.indices.delete(index=[ACCOUNTS, EMPLOYEES, PEOPLE, ACCOUNT2, NYC_TAXI], ignore_unavailable=True)
test_data_client.indices.delete(index=[ACCOUNTS, EMPLOYEES, PEOPLE, ACCOUNT2, NYC_TAXI, BOOKS], ignore_unavailable=True)


docsuite = partial(doctest.DocFileSuite,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,15 @@

package org.opensearch.sql.ppl;

import static org.opensearch.sql.legacy.TestsConstants.TEST_INDEX_ACCOUNT;
import static org.opensearch.sql.legacy.TestsConstants.TEST_INDEX_BANK;
import static org.opensearch.sql.legacy.TestsConstants.TEST_INDEX_BANK_WITH_NULL_VALUES;
import static org.opensearch.sql.legacy.TestsConstants.*;
Comment thread
MaxKsyunz marked this conversation as resolved.
Outdated
import static org.opensearch.sql.util.MatcherUtils.rows;
import static org.opensearch.sql.util.MatcherUtils.verifyDataRows;

import java.io.IOException;
import org.json.JSONObject;
import org.junit.Ignore;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;

public class WhereCommandIT extends PPLIntegTestCase {
Expand All @@ -23,6 +24,7 @@ public void init() throws IOException {
loadIndex(Index.ACCOUNT);
loadIndex(Index.BANK_WITH_NULL_VALUES);
loadIndex(Index.BANK);
loadIndex(Index.GAME_OF_THRONES);
}

@Test
Expand Down Expand Up @@ -110,4 +112,22 @@ public void testRelevanceFunction() throws IOException {
TEST_INDEX_BANK));
verifyDataRows(result, rows("Hattie"));
}

@Test
public void testMatchPhraseFunction() throws IOException {
JSONObject result =
executeQuery(
String.format(
"source=%s | where match_phrase(firstname, 'Hattie') | fields firstname", TEST_INDEX_BANK));
verifyDataRows(result, rows("Hattie"));
}

@Test
public void testMathPhraseWithSlop() throws IOException {
JSONObject result =
executeQuery(
String.format(
"source=%s | where match_phrase(firstname, 'Hattie', slop = 2) | fields firstname", TEST_INDEX_BANK));
verifyDataRows(result, rows("Hattie"));
}
Comment thread
MaxKsyunz marked this conversation as resolved.
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import org.opensearch.sql.opensearch.storage.script.filter.lucene.RangeQuery.Comparison;
import org.opensearch.sql.opensearch.storage.script.filter.lucene.TermQuery;
import org.opensearch.sql.opensearch.storage.script.filter.lucene.WildcardQuery;
import org.opensearch.sql.opensearch.storage.script.filter.lucene.relevance.MatchPhraseQuery;
import org.opensearch.sql.opensearch.storage.script.filter.lucene.relevance.MatchQuery;
import org.opensearch.sql.opensearch.storage.serialization.ExpressionSerializer;

Expand All @@ -52,6 +53,7 @@ public class FilterQueryBuilder extends ExpressionNodeVisitor<QueryBuilder, Obje
.put(BuiltinFunctionName.GTE.getName(), new RangeQuery(Comparison.GTE))
.put(BuiltinFunctionName.LIKE.getName(), new WildcardQuery())
.put(BuiltinFunctionName.MATCH.getName(), new MatchQuery())
.put(BuiltinFunctionName.MATCH_PHRASE.getName(), new MatchPhraseQuery())
.put(BuiltinFunctionName.QUERY.getName(), new MatchQuery())
.put(BuiltinFunctionName.MATCH_QUERY.getName(), new MatchQuery())
.put(BuiltinFunctionName.MATCHQUERY.getName(), new MatchQuery())
Expand Down
Loading