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// -- SuggesterGeoMapping --
8
9// SuggesterGeoMapping provides a mapping for a geolocation context in a suggester.
10// See https://www.elastic.co/guide/en/elasticsearch/reference/6.8/suggester-context.html#_geo_location_mapping.
11type SuggesterGeoMapping struct {
12	name             string
13	defaultLocations []*GeoPoint
14	precision        []string
15	neighbors        *bool
16	fieldName        string
17}
18
19// NewSuggesterGeoMapping creates a new SuggesterGeoMapping.
20func NewSuggesterGeoMapping(name string) *SuggesterGeoMapping {
21	return &SuggesterGeoMapping{
22		name: name,
23	}
24}
25
26func (q *SuggesterGeoMapping) DefaultLocations(locations ...*GeoPoint) *SuggesterGeoMapping {
27	q.defaultLocations = append(q.defaultLocations, locations...)
28	return q
29}
30
31func (q *SuggesterGeoMapping) Precision(precision ...string) *SuggesterGeoMapping {
32	q.precision = append(q.precision, precision...)
33	return q
34}
35
36func (q *SuggesterGeoMapping) Neighbors(neighbors bool) *SuggesterGeoMapping {
37	q.neighbors = &neighbors
38	return q
39}
40
41func (q *SuggesterGeoMapping) FieldName(fieldName string) *SuggesterGeoMapping {
42	q.fieldName = fieldName
43	return q
44}
45
46// Source returns a map that will be used to serialize the context query as JSON.
47func (q *SuggesterGeoMapping) Source() (interface{}, error) {
48	source := make(map[string]interface{})
49
50	x := make(map[string]interface{})
51	source[q.name] = x
52
53	x["type"] = "geo"
54
55	if len(q.precision) > 0 {
56		x["precision"] = q.precision
57	}
58	if q.neighbors != nil {
59		x["neighbors"] = *q.neighbors
60	}
61
62	switch len(q.defaultLocations) {
63	case 0:
64	case 1:
65		x["default"] = q.defaultLocations[0].Source()
66	default:
67		var arr []interface{}
68		for _, p := range q.defaultLocations {
69			arr = append(arr, p.Source())
70		}
71		x["default"] = arr
72	}
73
74	if q.fieldName != "" {
75		x["path"] = q.fieldName
76	}
77	return source, nil
78}
79
80// -- SuggesterGeoQuery --
81
82// SuggesterGeoQuery provides querying a geolocation context in a suggester.
83// See https://www.elastic.co/guide/en/elasticsearch/reference/6.8/suggester-context.html#_geo_location_query
84type SuggesterGeoQuery struct {
85	name       string
86	location   *GeoPoint
87	precision  string
88	neighbours []string
89	boost      *int
90}
91
92// NewSuggesterGeoQuery creates a new SuggesterGeoQuery.
93func NewSuggesterGeoQuery(name string, location *GeoPoint) *SuggesterGeoQuery {
94	return &SuggesterGeoQuery{
95		name:       name,
96		location:   location,
97		neighbours: make([]string, 0),
98	}
99}
100
101func (q *SuggesterGeoQuery) Precision(precision string) *SuggesterGeoQuery {
102	q.precision = precision
103	return q
104}
105
106func (q *SuggesterGeoQuery) Neighbours(neighbours ...string) *SuggesterGeoQuery {
107	q.neighbours = append(q.neighbours, neighbours...)
108	return q
109}
110
111func (q *SuggesterGeoQuery) Boost(boost int) *SuggesterGeoQuery {
112	q.boost = &boost
113	return q
114}
115
116// Source returns a map that will be used to serialize the context query as JSON.
117func (q *SuggesterGeoQuery) Source() (interface{}, error) {
118	source := make(map[string]interface{})
119
120	x := make(map[string]interface{})
121	source[q.name] = x
122
123	if q.location != nil {
124		x["context"] = q.location.Source()
125	}
126	if q.precision != "" {
127		x["precision"] = q.precision
128	}
129	if q.boost != nil {
130		x["boost"] = q.boost
131	}
132	switch len(q.neighbours) {
133	case 0:
134	case 1:
135		x["neighbours"] = q.neighbours[0]
136	default:
137		x["neighbours"] = q.neighbours
138	}
139
140	return source, nil
141}
142
143type SuggesterGeoIndex struct {
144	name      string
145	locations []*GeoPoint
146}
147
148// NewSuggesterGeoQuery creates a new SuggesterGeoQuery.
149func NewSuggesterGeoIndex(name string) *SuggesterGeoIndex {
150	return &SuggesterGeoIndex{
151		name: name,
152	}
153}
154
155func (q *SuggesterGeoIndex) Locations(locations ...*GeoPoint) *SuggesterGeoIndex {
156	q.locations = append(q.locations, locations...)
157	return q
158}
159
160// Source returns a map that will be used to serialize the context query as JSON.
161func (q *SuggesterGeoIndex) Source() (interface{}, error) {
162	source := make(map[string]interface{})
163
164	switch len(q.locations) {
165	case 0:
166		source[q.name] = make([]string, 0)
167	case 1:
168		source[q.name] = q.locations[0].Source()
169	default:
170		var arr []interface{}
171		for _, p := range q.locations {
172			arr = append(arr, p.Source())
173		}
174		source[q.name] = arr
175	}
176
177	return source, nil
178}
179