1// Copyright 2012-present Oliver Eilhard. All rights reserved.
2// Use of this source code is governed by a MIT-license.
3// See http://olivere.mit-license.org/license.txt for details.
4
5package elastic
6
7// FuzzyQuery uses similarity based on Levenshtein edit distance for
8// string fields, and a +/- margin on numeric and date fields.
9//
10// For more details, see
11// https://www.elastic.co/guide/en/elasticsearch/reference/6.7/query-dsl-fuzzy-query.html
12type FuzzyQuery struct {
13	name           string
14	value          interface{}
15	boost          *float64
16	fuzziness      interface{}
17	prefixLength   *int
18	maxExpansions  *int
19	transpositions *bool
20	rewrite        string
21	queryName      string
22}
23
24// NewFuzzyQuery creates a new fuzzy query.
25func NewFuzzyQuery(name string, value interface{}) *FuzzyQuery {
26	q := &FuzzyQuery{
27		name:  name,
28		value: value,
29	}
30	return q
31}
32
33// Boost sets the boost for this query. Documents matching this query will
34// (in addition to the normal weightings) have their score multiplied by
35// the boost provided.
36func (q *FuzzyQuery) Boost(boost float64) *FuzzyQuery {
37	q.boost = &boost
38	return q
39}
40
41// Fuzziness can be an integer/long like 0, 1 or 2 as well as strings
42// like "auto", "0..1", "1..4" or "0.0..1.0".
43func (q *FuzzyQuery) Fuzziness(fuzziness interface{}) *FuzzyQuery {
44	q.fuzziness = fuzziness
45	return q
46}
47
48func (q *FuzzyQuery) PrefixLength(prefixLength int) *FuzzyQuery {
49	q.prefixLength = &prefixLength
50	return q
51}
52
53func (q *FuzzyQuery) MaxExpansions(maxExpansions int) *FuzzyQuery {
54	q.maxExpansions = &maxExpansions
55	return q
56}
57
58func (q *FuzzyQuery) Transpositions(transpositions bool) *FuzzyQuery {
59	q.transpositions = &transpositions
60	return q
61}
62
63func (q *FuzzyQuery) Rewrite(rewrite string) *FuzzyQuery {
64	q.rewrite = rewrite
65	return q
66}
67
68// QueryName sets the query name for the filter that can be used when
69// searching for matched filters per hit.
70func (q *FuzzyQuery) QueryName(queryName string) *FuzzyQuery {
71	q.queryName = queryName
72	return q
73}
74
75// Source returns JSON for the function score query.
76func (q *FuzzyQuery) Source() (interface{}, error) {
77	// {
78	//	"fuzzy" : {
79	//		"user" : {
80	//      "value" : "ki",
81	//      "boost" : 1.0,
82	//      "fuzziness" : 2,
83	//      "prefix_length" : 0,
84	//      "max_expansions" : 100
85	//    }
86	// }
87
88	source := make(map[string]interface{})
89	query := make(map[string]interface{})
90	source["fuzzy"] = query
91
92	fq := make(map[string]interface{})
93	query[q.name] = fq
94
95	fq["value"] = q.value
96
97	if q.boost != nil {
98		fq["boost"] = *q.boost
99	}
100	if q.transpositions != nil {
101		fq["transpositions"] = *q.transpositions
102	}
103	if q.fuzziness != nil {
104		fq["fuzziness"] = q.fuzziness
105	}
106	if q.prefixLength != nil {
107		fq["prefix_length"] = *q.prefixLength
108	}
109	if q.maxExpansions != nil {
110		fq["max_expansions"] = *q.maxExpansions
111	}
112	if q.rewrite != "" {
113		fq["rewrite"] = q.rewrite
114	}
115	if q.queryName != "" {
116		fq["_name"] = q.queryName
117	}
118
119	return source, nil
120}
121