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
}

🌱 Back to Garden