From 3a2e23b80410e65d8a6a27282fcbca1bd74d5f13 Mon Sep 17 00:00:00 2001
From: Jan Semmelink <jan@uafrica.com>
Date: Fri, 12 Nov 2021 12:36:12 +0200
Subject: [PATCH] Update search to do wildcard searches on documents

---
 search/document_store.go   | 11 +++++++++--
 search/opensearch_types.go | 17 +++++++++++------
 search/time_series.go      |  3 ++-
 search/writer.go           | 31 -------------------------------
 4 files changed, 22 insertions(+), 40 deletions(-)

diff --git a/search/document_store.go b/search/document_store.go
index bec6755..24e5fbd 100644
--- a/search/document_store.go
+++ b/search/document_store.go
@@ -197,7 +197,8 @@ func (ds *documentStore) Search(query Query, limit int64) (ids []string, totalCo
 	}
 	jsonBody, _ := json.Marshal(body)
 	search := opensearchapi.SearchRequest{
-		Body: bytes.NewReader(jsonBody),
+		Index: []string{ds.name},
+		Body:  bytes.NewReader(jsonBody),
 	}
 
 	searchResponse, err := search.Do(context.Background(), ds.w.client)
@@ -214,12 +215,18 @@ func (ds *documentStore) Search(query Query, limit int64) (ids []string, totalCo
 		return
 	}
 
+	bodyData, _ := ioutil.ReadAll(searchResponse.Body)
+	logger.Debugf("Response Body: %s", string(bodyData))
+
 	resBodyPtrValue := reflect.New(ds.searchResponseBodyType)
-	if err = json.NewDecoder(searchResponse.Body).Decode(resBodyPtrValue.Interface()); err != nil {
+	// if err = json.NewDecoder(searchResponse.Body).Decode(resBodyPtrValue.Interface()); err != nil {
+	if err = json.Unmarshal(bodyData, resBodyPtrValue.Interface()); err != nil {
 		err = errors.Wrapf(err, "cannot decode search response body")
 		return
 	}
 
+	logger.Debugf("Response Parsed: %+v", resBodyPtrValue.Interface())
+
 	hitsTotalValue, err := reflection.Get(resBodyPtrValue, ".hits.total.value")
 	if err != nil {
 		err = errors.Wrapf(err, "cannot get total nr of hits")
diff --git a/search/opensearch_types.go b/search/opensearch_types.go
index aeb65b3..cdbe211 100644
--- a/search/opensearch_types.go
+++ b/search/opensearch_types.go
@@ -40,18 +40,23 @@ type SearchRequestBody struct {
 
 type Query struct {
 	//one of:
-	Match      *QueryNameValue  `json:"match,omitempty" doc:"<field>:<value>"`
-	Term       *QueryNameValue  `json:"term,omitempty"`
-	Range      *QueryRange      `json:"range,omitempty"`
-	MultiMatch *QueryMultiMatch `json:"multi_match,omitempty"`
-	Bool       *QueryBool       `json:"bool,omitempty"`
+	Match       *QueryNameValue  `json:"match,omitempty" doc:"<field>:<value>"`
+	Term        *QueryNameValue  `json:"term,omitempty"`
+	Range       *QueryRange      `json:"range,omitempty"`
+	MultiMatch  *QueryMultiMatch `json:"multi_match,omitempty"`
+	Bool        *QueryBool       `json:"bool,omitempty"`
+	QueryString *QueryString     `json:"query_string,omitempty"`
 }
 
 type QueryMultiMatch struct {
-	Query  string   `json:"query" doc:"Text search in below fields"`
+	Query  string   `json:"query" doc:"Full value match search in selected fields"`
 	Fields []string `json:"fields,omitempty" doc:"List of fields"`
 }
 
+type QueryString struct {
+	Query string `json:"query" doc:"Text search with partial matches, using asterisk for optional or question mark for required wildcards before and/or after text"`
+}
+
 //https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-bool-query.html
 type QueryBool struct {
 	Must    []Query `json:"must,omitempty" docs:"List of things that must appear in matching documents and will contribute to the score."`
diff --git a/search/time_series.go b/search/time_series.go
index 4420e3f..f867470 100644
--- a/search/time_series.go
+++ b/search/time_series.go
@@ -385,7 +385,8 @@ func (ts *timeSeries) Search(query Query, limit int64) (docs interface{}, totalC
 	}
 	jsonBody, _ := json.Marshal(body)
 	search := opensearchapi.SearchRequest{
-		Body: bytes.NewReader(jsonBody),
+		Index: []string{ts.name + "-*"},
+		Body:  bytes.NewReader(jsonBody),
 	}
 
 	searchResponse, err := search.Do(context.Background(), ts.w.client)
diff --git a/search/writer.go b/search/writer.go
index 201accb..17a6dd0 100644
--- a/search/writer.go
+++ b/search/writer.go
@@ -1,7 +1,6 @@
 package search
 
 import (
-	"context"
 	"crypto/tls"
 	"encoding/json"
 	"net/http"
@@ -114,36 +113,6 @@ func (writer writer) Write(indexName string, id string, doc interface{}) (*Index
 	return &res, nil
 }
 
-func (writer writer) Search() ([]interface{}, error) {
-	if writer.client == nil {
-		return nil, errors.Errorf("writer closed")
-	}
-	// Search for the document.
-	content := strings.NewReader(`{
-       "size": 5,
-       "query": {
-           "multi_match": {
-           "query": "miller",
-           "fields": ["title^2", "director"]
-           }
-      }
-    }`)
-
-	search := opensearchapi.SearchRequest{
-		Body: content,
-	}
-
-	searchResponse, err := search.Do(context.Background(), writer.client)
-	if err != nil {
-		return nil, errors.Wrapf(err, "failed to search document")
-	}
-	var res interface{}
-	if err := json.NewDecoder(searchResponse.Body).Decode(&res); err != nil {
-		return nil, errors.Wrapf(err, "failed to decode JSON body")
-	}
-	return nil, errors.Errorf("NYI search result processing: %v", res)
-}
-
 type CreateResponse struct {
 	Error *Error `json:"error,omitempty"`
 }
-- 
GitLab