Skip to content

Commit

Permalink
feature: add MatchPhrase query
Browse files Browse the repository at this point in the history
  • Loading branch information
GokselKUCUKSAHIN committed Jan 27, 2025
1 parent 06c7dde commit eb29458
Show file tree
Hide file tree
Showing 2 changed files with 256 additions and 0 deletions.
129 changes: 129 additions & 0 deletions es/match_phrase_query.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
package es

import ZeroTermsQuery "github.com/Trendyol/es-query-builder/es/enums/zero-terms-query"

type matchPhraseType Object

// MatchPhrase creates a new es.matchPhraseType object with the specified field and query.
//
// This function initializes an es.matchPhraseType object for a match phrase query, where the key
// is the field name and query is the value to search for in that field. This is used
// to construct queries that match the specified value in the given field.
//
// Example usage:
//
// m := es.MatchPhrase("title", "es-query-builder")
// // m now contains an es.matchPhraseType object that matches the query "es-query-builder" in the "title" field.
//
// Parameters:
// - key: A string representing the field name for the match phrase query.
// - query: The value to be matched in the specified field. The type is generic.
//
// Returns:
//
// An es.matchPhraseType object containing the specified match phrase query.
func MatchPhrase[T any](key string, query T) matchPhraseType {
return matchPhraseType{
"match_phrase": Object{
key: Object{
"query": query,
},
},
}
}

// Analyzer sets the "analyzer" field in the match phrase query.
//
// This method specifies the analyzer to use for the match phrase query, which determines
// how the input text is processed during analysis (e.g., tokenization and normalization).
// Custom analyzers can be used to tailor the query behavior to specific requirements.
//
// Example usage:
//
// m := es.MatchPhrase("title", "es-query-builder").Analyzer("custom_analyzer")
// // m now has an "analyzer" field set to "custom_analyzer" in the match phrase query object.
//
// Parameters:
// - value: A string representing the name of the analyzer to use.
//
// Returns:
//
// The updated es.matchPhraseType object with the "analyzer" field set to the specified value.
func (m matchPhraseType) Analyzer(value string) matchPhraseType {
return m.putInTheField("analyzer", value)
}

// Boost sets the "boost" field in the match phrase query.
//
// This method configures the match phrase query to use a specified boost factor, which influences
// the relevance scoring of the matched documents.
//
// Example usage:
//
// m := es.MatchPhrase("title", "es-query-builder").Boost(1.5)
// // m now has a "boost" field set to 1.5 in the match phrase query object.
//
// Parameters:
// - boost: A float64 value representing the boost factor to be applied to the match phrase query.
//
// Returns:
//
// The updated es.matchPhraseType object with the "boost" field set to the specified value.
func (m matchPhraseType) Boost(boost float64) matchPhraseType {
return m.putInTheField("boost", boost)
}

// ZeroTermsQuery sets the "zero_terms_query" field in the match phrase query.
//
// This method configures the behavior of the match phrase query when no terms remain after analysis
// (for example, if all terms are stop words). The specified zero_terms_query value determines
// how to handle this scenario, with options like "all" to match all documents or "none" to
// match none.
//
// Example usage:
//
// m := es.MatchPhrase("title", "es-query-builder").ZeroTermsQuery(zerotermsquery.All)
// // m now has a "zero_terms_query" field set to "all" in the match phrase query object.
//
// Parameters:
// - zeroTermsQuery: A zerotermsquery.ZeroTermsQuery value that specifies the behavior for zero-term queries.
//
// Returns:
//
// The updated es.matchPhraseType object with the "zero_terms_query" field set to the specified value.
func (m matchPhraseType) ZeroTermsQuery(zeroTermsQuery ZeroTermsQuery.ZeroTermsQuery) matchPhraseType {
return m.putInTheField("zero_terms_query", zeroTermsQuery)
}

// Slop sets the "slop" field in the match phrase query.
//
// This method specifies the allowed distance between terms in a phrase query, enabling more
// flexibility in matching phrases that may have slight variations in word order or spacing.
// A higher slop value allows more variation, while a slop of 0 requires exact matching.
//
// Example usage:
//
// m := es.MatchPhrase("title", "es-query-builder").Slop(2)
// // m now has a "slop" field set to 2 in the match phrase query object.
//
// Parameters:
// - slop: An integer representing the maximum allowed distance between terms.
//
// Returns:
//
// The updated es.matchPhraseType object with the "slop" field set to the specified value.
func (m matchPhraseType) Slop(slop int) matchPhraseType {
return m.putInTheField("slop", slop)
}

func (m matchPhraseType) putInTheField(key string, value any) matchPhraseType {
if matchPhrase, ok := m["match_phrase"].(Object); ok {
for _, fieldObj := range matchPhrase {
if fieldObject, foOk := fieldObj.(Object); foOk {
fieldObject[key] = value
break
}
}
}
return m
}
127 changes: 127 additions & 0 deletions es/match_phrase_query_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
package es_test

import (
"testing"

ZeroTermsQuery "github.com/Trendyol/es-query-builder/es/enums/zero-terms-query"

"github.com/Trendyol/es-query-builder/es"
"github.com/Trendyol/es-query-builder/test/assert"
)

//// Match Phrase ////

func Test_MatchPhrase_should_exist_on_es_package(t *testing.T) {
// Given When Then
assert.NotNil(t, es.MatchPhrase[any])
}

func Test_MatchPhrase_method_should_create_matchPhraseType(t *testing.T) {
// Given
b := es.MatchPhrase("key", "value")

// Then
assert.NotNil(t, b)
assert.IsTypeString(t, "es.matchPhraseType", b)
}

func Test_MatchPhrase_should_have_Analyzer_method(t *testing.T) {
// Given
match := es.MatchPhrase("key", "value")

// When Then
assert.NotNil(t, match.Analyzer)
}

func Test_MatchPhrase_Analyzer_should_create_json_with_analyzer_field_inside_match_phrase(t *testing.T) {
// Given
query := es.NewQuery(
es.MatchPhrase("type", "Folder").
Analyzer("standart"),
)

// When Then
assert.NotNil(t, query)
bodyJSON := assert.MarshalWithoutError(t, query)
assert.Equal(t, "{\"query\":{\"match_phrase\":{\"type\":{\"analyzer\":\"standart\",\"query\":\"Folder\"}}}}", bodyJSON)
}

func Test_MatchPhrase_should_have_Boost_method(t *testing.T) {
// Given
match := es.MatchPhrase("key", "value")

// When Then
assert.NotNil(t, match.Boost)
}

func Test_MatchPhrase_Boost_should_create_json_with_boost_field_inside_match_phrase(t *testing.T) {
// Given
query := es.NewQuery(
es.MatchPhrase("type", "Folder").
Boost(3.14),
)

// When Then
assert.NotNil(t, query)
bodyJSON := assert.MarshalWithoutError(t, query)
assert.Equal(t, "{\"query\":{\"match_phrase\":{\"type\":{\"boost\":3.14,\"query\":\"Folder\"}}}}", bodyJSON)
}

func Test_MatchPhrase_should_have_Slop_method(t *testing.T) {
// Given
match := es.MatchPhrase("key", "value")

// When Then
assert.NotNil(t, match.Slop)
}

func Test_MatchPhrase_Slop_should_create_json_with_slop_field_inside_match_phrase(t *testing.T) {
// Given
query := es.NewQuery(
es.MatchPhrase("type", "Folder").
Slop(3),
)

// When Then
assert.NotNil(t, query)
bodyJSON := assert.MarshalWithoutError(t, query)
assert.Equal(t, "{\"query\":{\"match_phrase\":{\"type\":{\"query\":\"Folder\",\"slop\":3}}}}", bodyJSON)
}

func Test_MatchPhrase_should_have_ZeroTermsQuery_method(t *testing.T) {
// Given
match := es.MatchPhrase("key", "value")

// When Then
assert.NotNil(t, match.ZeroTermsQuery)
}

func Test_MatchPhrase_ZeroTermsQuery_should_create_json_with_zero_terms_query_field_inside_match_phrase(t *testing.T) {
// Given
query := es.NewQuery(
es.MatchPhrase("type", "Folder").
ZeroTermsQuery(ZeroTermsQuery.All),
)

// When Then
assert.NotNil(t, query)
bodyJSON := assert.MarshalWithoutError(t, query)
assert.Equal(t, "{\"query\":{\"match_phrase\":{\"type\":{\"query\":\"Folder\",\"zero_terms_query\":\"all\"}}}}", bodyJSON)
}

func Test_MatchPhrase_should_create_json_with_match_phrase_field_inside_query(t *testing.T) {
// Given
query := es.NewQuery(
es.MatchPhrase("message", "this is a test").
Analyzer("standart").
Boost(2.14).
Slop(9).
ZeroTermsQuery(ZeroTermsQuery.None),
)

// When Then
assert.NotNil(t, query)
bodyJSON := assert.MarshalWithoutError(t, query)
// nolint:golint,lll
assert.Equal(t, "{\"query\":{\"match_phrase\":{\"message\":{\"analyzer\":\"standart\",\"boost\":2.14,\"query\":\"this is a test\",\"slop\":9,\"zero_terms_query\":\"none\"}}}}", bodyJSON)
}

0 comments on commit eb29458

Please sign in to comment.