Skip to content

Commit

Permalink
Merge pull request #8 from Trendyol/feature/regexp
Browse files Browse the repository at this point in the history
Feature/regexp
  • Loading branch information
GokselKUCUKSAHIN authored Sep 15, 2024
2 parents e17fb2a + 8a9183e commit a7a8931
Show file tree
Hide file tree
Showing 3 changed files with 246 additions and 0 deletions.
107 changes: 107 additions & 0 deletions es/regexp_query.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
package es

type regexpType Object

// Regexp creates a new regexpType object with the specified key-value pair.
//
// This function initializes a regexpType object with a single regexp query, where the
// key is the field name and the value is the regexp to search for. This is typically
// used to construct a regexp query in search queries.
//
// Example usage:
//
// t := Regexp("endpoint", "/books/.*")
// // t now contains a regexpType object with a regexp query for the "endpoint" field.
//
// Parameters:
// - key: A string representing the field name for the regexp query.
// - value: The value to be searched for in the specified field. The type is regexp.
//
// Returns:
//
// A regexpType object containing the specified regexp query.
func Regexp(key string, value string) regexpType {
return regexpType{
"regexp": Object{
key: Object{
"value": value,
},
},
}
}

func (r regexpType) putInTheField(key string, value any) regexpType {
if regexp, ok := r["regexp"].(Object); ok {
for field := range regexp {
if fieldObject, foOk := regexp[field].(Object); foOk {
fieldObject[key] = value
}
}
}
return r
}

// Flags Enables optional operators for the regular expression.
// Example usage:
//
// regexp := Regexp("endpoint", "/books/.*").Flags("ALL")
// // regexp now a "flags" field set "ALL" in the regexp query object.
//
// Parameters:
// - flags: A string value representing flags value to be applied to the regexp query.
//
// Returns:
//
// The updated regexp object with the "flags" field set to the specified value.
func (r regexpType) Flags(flags string) regexpType {
return r.putInTheField("flags", flags)
}

// CaseInsensitive Allows case insensitive matching of the regular expression
// value with the indexed field values when set to true.
// Example usage:
//
// regexp := Regexp("endpoint", "/books/.*").CaseInsensitive(true)
// // regexp now a "case_insensitive" field set true in the regexp query object.
//
// Parameters:
// - caseInsensitive: A bool value representing case insensitive value to be applied to the regexp query.
//
// Returns:
//
// The updated regexp object with the "case_insensitive" field set to the specified value.
func (r regexpType) CaseInsensitive(caseInsensitive bool) regexpType {
return r.putInTheField("case_insensitive", caseInsensitive)
}

// MaxDeterminizedStates Maximum number of automaton states required for the query.
// Example usage:
//
// regexp := Regexp("endpoint", "/books/.*").MaxDeterminizedStates(10000)
// // regexp now a "max_determinized_states" field set 10000 in the regexp query object.
//
// Parameters:
// - maxDeterminizedStates: A bool value representing max_determinized_states value to be applied to the regexp query.
//
// Returns:
//
// The updated regexp object with the "max_determinized_states" field set to the specified value.
func (r regexpType) MaxDeterminizedStates(maxDeterminizedStates int) regexpType {
return r.putInTheField("max_determinized_states", maxDeterminizedStates)
}

// ReWrite Method used to rewrite the query.
// Example usage:
//
// regexp := Regexp("endpoint", "/books/.*").ReWrite("a")
// // regexp now a "rewrite" field set "a" in the regexp query object.
//
// Parameters:
// - rewrite: A string value representing rewrite value to be applied to the regexp query.
//
// Returns:
//
// The updated regexp object with the "rewrite" field set to the specified value.
func (r regexpType) ReWrite(rewrite string) regexpType {
return r.putInTheField("rewrite", rewrite)
}
88 changes: 88 additions & 0 deletions es/regexp_query_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package es_test

import (
"testing"

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

//// Regexp ////

func Test_Regexp_should_exist_on_es_package(t *testing.T) {
// Given When Then
assert.NotNil(t, es.Regexp)
}

func Test_Regexp_should_create_json_with_regexp_field_inside_query(t *testing.T) {
// Given
query := es.NewQuery(
es.Regexp("endpoint", "/books/.*"),
)

// When Then
assert.NotNil(t, query)
bodyJSON := assert.MarshalWithoutError(t, query)
assert.Equal(t, "{\"query\":{\"regexp\":{\"endpoint\":{\"value\":\"/books/.*\"}}}}", bodyJSON)
}

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

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

func Test_Regexp_should_create_json_with_match_all_field_inside_caseinsensitive_query(t *testing.T) {
// Given
query := es.NewQuery(
es.Regexp("key", "value1").
CaseInsensitive(false),
)

// When Then
assert.NotNil(t, query)
bodyJSON := assert.MarshalWithoutError(t, query)
assert.Equal(t, "{\"query\":{\"regexp\":{\"key\":{\"case_insensitive\":false,\"value\":\"value1\"}}}}", bodyJSON)
}

func Test_Regexp_should_create_json_with_match_all_field_inside_maxdeterminizedstates_query(t *testing.T) {
// Given
query := es.NewQuery(
es.Regexp("key", "value1").
MaxDeterminizedStates(1000),
)

// When Then
assert.NotNil(t, query)
bodyJSON := assert.MarshalWithoutError(t, query)
assert.Equal(t, "{\"query\":{\"regexp\":{\"key\":{\"max_determinized_states\":1000,\"value\":\"value1\"}}}}", bodyJSON)
}

func Test_Regexp_should_create_json_with_match_all_field_inside_rewrite_query(t *testing.T) {
// Given
query := es.NewQuery(
es.Regexp("key", "value1").
ReWrite("a"),
)

// When Then
assert.NotNil(t, query)
bodyJSON := assert.MarshalWithoutError(t, query)
assert.Equal(t, "{\"query\":{\"regexp\":{\"key\":{\"rewrite\":\"a\",\"value\":\"value1\"}}}}", bodyJSON)
}

func Test_Regexp_should_create_json_with_match_all_field_inside_flags_query(t *testing.T) {
// Given
query := es.NewQuery(
es.Regexp("key", "value1").
Flags("ALL"),
)

// When Then
assert.NotNil(t, query)
bodyJSON := assert.MarshalWithoutError(t, query)
assert.Equal(t, "{\"query\":{\"regexp\":{\"key\":{\"flags\":\"ALL\",\"value\":\"value1\"}}}}", bodyJSON)
}
51 changes: 51 additions & 0 deletions internal/testing/regexp_query_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package testing

import (
"encoding/json"
"github.com/Trendyol/es-query-builder/es"
"github.com/bayraktugrul/go-await"
"github.com/stretchr/testify/assert"
)

func (s *testSuite) Test_it_should_return_documents_that_filtered_by_regexp_query() {
// Given
foo := FooDocument{
Id: "10",
Foo: "foo",
}
bar := FooDocument{
Id: "20",
Foo: "bar",
}
georgeOrwell := FooDocument{
Id: "30",
Foo: "george orwell",
}
georgeBest := FooDocument{
Id: "40",
Foo: "george best",
}

s.ElasticsearchRepository.BulkInsert([]FooDocument{foo, bar, georgeOrwell, georgeBest})
await.New().Await(func() bool { return s.ElasticsearchRepository.Exists(foo.Id) })
await.New().Await(func() bool { return s.ElasticsearchRepository.Exists(bar.Id) })
await.New().Await(func() bool { return s.ElasticsearchRepository.Exists(georgeOrwell.Id) })
await.New().Await(func() bool { return s.ElasticsearchRepository.Exists(georgeBest.Id) })

//f* OR bar
query := es.NewQuery(
es.Regexp("foo", "george.*"),
)
bodyJSON, _ := json.Marshal(query)

// When
result, err := s.ElasticsearchRepository.Search(string(bodyJSON))

// Then
assert.Nil(s.T(), err)
assert.Equal(s.T(), len(result), 2)
assert.Equal(s.T(), result[0].Foo, "george orwell")
assert.Equal(s.T(), result[1].Foo, "george best")

s.ElasticsearchRepository.BulkDelete([]string{foo.Id, bar.Id, georgeOrwell.Id, georgeBest.Id})
}

0 comments on commit a7a8931

Please sign in to comment.