func Search(request) (string, error) {
var buf bytes.Buffer
should, must, mustNot, filter := createQueryLists(request)
// Currently, "must" clauses are not being used. All previous "must" have been changed to "filter".
// The plan is to use "must" only for mandatory fuzzy queries (ie., "match"-type).
query := map[string]interface{}{
//"min_score": 0.001,
"query": map[string]interface{}{
"bool": map[string]interface{}{
"should": *should,
"must": *must,
"must_not": *mustNot,
"filter": *filter,
},
},
}
if err := json.NewEncoder(&buf).Encode(query); err != nil {
log.Printf("Error encoding query: %s\n", err)
return "", err
}
DebugMode, _ := strconv.ParseBool(os.Getenv("DEBUG_MODE"))
if DebugMode == true {
fmt.Println("-------------------------------------")
log.Println(buf.String())
fmt.Println("-------------------------------------")
}
es := ElasticGetClient()
index := "index_name"
page := request.PageNumber
if page == 0 {
page = 1
}
resultPerPage := request.PageSize
res, err := es.Search(
es.Search.WithContext(context.Background()),
es.Search.WithIndex(index),
es.Search.WithBody(&buf),
es.Search.WithTrackTotalHits(true),
es.Search.WithFrom(resultPerPage*(page-1)),
es.Search.WithSize(resultPerPage),
es.Search.WithSort("_score", interview+":desc"),
es.Search.WithPretty(),
)
if err != nil {
log.Println("[-] Error getting response.json: " + err.Error())
return "", err
}
defer res.Body.Close()
if res.StatusCode != 200 {
log.Println("[-] ElasticSearch Response Status: " + strconv.Itoa(res.StatusCode))
return "", err
}
BodyBytes, err := io.ReadAll(res.Body)
return string(BodyBytes), nil
}
func createQueryLists(request *service.RequestJson) (
*[]*map[string]interface{},
*[]*map[string]interface{},
*[]*map[string]interface{},
*[]*map[string]interface{},
) {
var should, must, mustNot, filter []*map[string]interface{} // Not all variables must be filled
must = append(must, CreateQueryItem(match, "name", request.Name, 1))
must = append(must, CreateQueryItem(match, "middle_name", request.MiddleName, 1))
must = append(must, CreateQueryItem(match, "nickname", request.Nickname, 1))
must = append(must, createTimeIntervalQuery(t1, t2, "birthday"))
/// (...)
return &should, &must, &mustNot, &filter
}
func CreateQueryItem(queryType, fieldName, variable string, boost float32) *map[string]interface{} {
if boost != 1 {
value := make(map[string]string)
switch queryType {
case term:
value["value"] = variable
case match:
value["query"] = variable
}
value["boost"] = fmt.Sprintf("%.2f", boost)
query := map[string]interface{}{
queryType: map[string]interface{}{
fieldName: value,
},
}
return &query
}
query := map[string]interface{}{
queryType: map[string]interface{}{
fieldName: variable,
},
}
return &query
}
func createTimeIntervalQuery(date1, date2 time.Time, fieldName string) *map[string]interface{} {
interval := make(map[string]string)
if date1.Before(date2) {
interval["gte"] = date1.Format(layout)
interval["lte"] = date2.Format(layout)
} else {
interval["gte"] = date2.Format(layout)
interval["lte"] = date1.Format(layout)
}
rangeEntry := map[string]interface{}{
"range": map[string]interface{}{
fieldName: interval,
},
}
return &rangeEntry
}