func NewQueryString(field, query string) QueryString {
	return QueryString{"", field, query, "", "", nil, false}
}
QueryString based search
package elastigo
import (
	"encoding/json"
	"fmt"
	"strings"
)
func Query() *QueryDsl {
	return &QueryDsl{}
}
type QueryDsl struct {
	QueryEmbed
	FilterVal *FilterOp `json:"filter,omitempty"`
}
type QueryEmbed struct {
	MatchAll      *MatchAll              `json:"match_all,omitempty"`
	Terms         map[string]string      `json:"term,omitempty"`
	Qs            *QueryString           `json:"query_string,omitempty"`
	MultiMatch    *MultiMatch            `json:"multi_match,omitempty"`
	FunctionScore map[string]interface{} `json:"function_score,omitempty"`
}
func (qd *QueryDsl) MarshalJSON() ([]byte, error) {
	q := qd.QueryEmbed
	hasQuery := false
	if q.Qs != nil || len(q.Terms) > 0 || q.MatchAll != nil || q.MultiMatch != nil {
		hasQuery = true
	}
	if qd.FilterVal != nil && hasQuery {
		queryB, err := json.Marshal(q)
		if err != nil {
			return queryB, err
		}
		filterB, err := json.Marshal(qd.FilterVal)
		if err != nil {
			return filterB, err
		}
		return []byte(fmt.Sprintf(`{"filtered":{"query":%s,"filter":%s}}`, queryB, filterB)), nil
	}
	return json.Marshal(q)
}
func (q *QueryDsl) All() *QueryDsl {
	q.MatchAll = &MatchAll{""}
	return q
}
func (q *QueryDsl) Range(fop *FilterOp) *QueryDsl {
	if q.FilterVal == nil {
		q.FilterVal = fop
		return q
	}
	return q
}
func (q *QueryDsl) Term(name, value string) *QueryDsl {
	if len(q.Terms) == 0 {
		q.Terms = make(map[string]string)
	}
	q.Terms[name] = value
	return q
}
func (q *QueryDsl) FunctionScore(mode string, functions ...map[string]interface{}) *QueryDsl {
	q.QueryEmbed.FunctionScore = map[string]interface{}{
		"functions":  functions,
		"score_mode": mode,
	}
	return q
}
func (q *QueryDsl) Search(searchFor string) *QueryDsl {
	qs := NewQueryString("", "")
	q.QueryEmbed.Qs = &qs
	q.QueryEmbed.Qs.Query = searchFor
	return q
}
func (q *QueryDsl) Qs(qs *QueryString) *QueryDsl {
	q.QueryEmbed.Qs = qs
	return q
}
func (q *QueryDsl) SetLenient(lenient bool) *QueryDsl {
	q.QueryEmbed.Qs.Lenient = lenient
	return q
}
func (q *QueryDsl) Fields(fields, search, exists, missing string) *QueryDsl {
	fieldList := strings.Split(fields, ",")
	qs := NewQueryString("", "")
	q.QueryEmbed.Qs = &qs
	q.QueryEmbed.Qs.Query = search
	if len(fieldList) == 1 {
		q.QueryEmbed.Qs.DefaultField = fields
	} else {
		q.QueryEmbed.Qs.Fields = fieldList
	}
	q.QueryEmbed.Qs.Exists = exists
	q.QueryEmbed.Qs.Missing = missing
	return q
}
func (q *QueryDsl) Filter(f *FilterOp) *QueryDsl {
	q.FilterVal = f
	return q
}
func (q *QueryDsl) MultiMatch(s string, fields []string) *QueryDsl {
	q.QueryEmbed.MultiMatch = &MultiMatch{Query: s, Fields: fields}
	return q
}
type MultiMatch struct {
	Query  string   `json:"query"`
	Fields []string `json:"fields"`
}
type MatchAll struct {
	All string `json:"-"`
}
type QueryWrap struct {
	Qs QueryString `json:"query_string,omitempty"`
}