1 module vibe.db.mongo.impl.index;
2 
3 @safe:
4 
5 import core.time;
6 
7 import std.array;
8 import std.typecons;
9 
10 import vibe.db.mongo.collection;
11 import vibe.data.bson;
12 
13 deprecated("Use CreateIndexOptions instead")
14 enum IndexFlags {
15 	none = 0,
16 	unique = 1<<0,
17 	dropDuplicates = 1<<2,
18 	background = 1<<3,
19 	sparse = 1<<4,
20 	expireAfterSeconds = 1<<5,
21 
22 	None = none, /// Deprecated compatibility alias, use `none` instead.
23 	Unique = unique, /// Deprecated compatibility alias, use `unique` instead.
24 	DropDuplicates = dropDuplicates, /// Deprecated compatibility alias, use `dropDuplicates` instead.
25 	Background = background, /// Deprecated compatibility alias, use `background` instead.
26 	Sparse = sparse, /// Deprecated compatibility alias, use `sparse` instead.
27 	ExpireAfterSeconds = expireAfterSeconds, /// Deprecated compatibility alias, use `expireAfterSeconds` instead.
28 }
29 
30 struct IndexModel
31 {
32 	Bson keys = Bson.emptyObject;
33 	IndexOptions options;
34 
35 	/**
36 		Adds a single field or multikey index with a direction.
37 
38 		Call this method multiple times with different fields to create a
39 		compound index.
40 
41 		Params:
42 		  field = the name of the field to index
43 		  direction = `1` for ascending or `-1` for descending
44 
45 		Returns: this IndexModel instance (caller)
46 	*/
47 	ref IndexModel add(string field, int direction) return
48 	@safe {
49 		// bson objects keep order
50 		keys[field] = Bson(direction);
51 		return this;
52 	}
53 
54 	/**
55 		Adds an index with a given index type. Use `IndexType` for a type-safe
56 		setting of the string.
57 
58 		Params:
59 		  field = the name of the field to index
60 		  type = the index type to use
61 
62 		Returns: this IndexModel instance (caller)
63 	*/
64 	ref IndexModel add(string field, string type) return
65 	@safe {
66 		// bson objects keep order
67 		keys[field] = Bson(type);
68 		return this;
69 	}
70 
71 	/**
72 		Sets the options member of this IndexModel.
73 
74 		Returns: this IndexModel instance (caller)
75 	*/
76 	ref IndexModel withOptions(IndexOptions options) return
77 	@safe {
78 		this.options = options;
79 		return this;
80 	}
81 
82 	string name() const
83 	@property @safe {
84 		if (options.name.length)
85 		{
86 			return options.name;
87 		}
88 		else
89 		{
90 			auto indexname = appender!string();
91 			bool first = true;
92 			foreach (string key, value; keys.byKeyValue) {
93 				if (!first) indexname.put('_');
94 				else first = false;
95 				indexname.put(key);
96 				indexname.put('_');
97 
98 				if (value.type == Bson.Type..string)
99 					indexname.put(value.get!string);
100 				else
101 					indexname.put(value.toString());
102 			}
103 			return indexname.data;
104 		}
105 	}
106 }
107 
108 /**
109 	Specifies the different index types which are available for index creation.
110 
111 	See_Also: $(LINK https://docs.mongodb.com/manual/indexes/#index-types)
112 */
113 enum IndexType : string
114 {
115 	/**
116 		Legacy 2D plane index used in MongoDB 2.2 and earlier. Doesn't support
117 		GeoJSON objects. Uses planar geometry to return results.
118 
119 		See_Also: $(LINK https://docs.mongodb.com/manual/core/2d/)
120 	*/
121 	legacy2D = "2d",
122 
123 	/**
124 		2D sphere index that calculates geometries on an earth-like sphere.
125 		Supports storing as GeoJSON objects.
126 
127 		See_Also: $(LINK https://docs.mongodb.com/manual/core/2dsphere/)
128 	*/
129 	sphere2D = "2dsphere",
130 
131 	/**
132 		A geoHaystack index is a special index that is optimized to return
133 		results over small areas. geoHaystack indexes improve performance on
134 		queries that use flat geometry.
135 
136 		See_Also: $(LINK https://docs.mongodb.com/manual/core/geohaystack/)
137 	*/
138 	geoHaystack = "geoHaystack",
139 
140 	/**
141 		Creates a text index which supports searching for string content in a
142 		collection. These text indexes do not store language-specific stop words
143 		and stem the words in a collection to only store root words.
144 
145 		See_Also: $(LINK https://docs.mongodb.com/manual/core/index-text/)
146 	*/
147 	text = "text",
148 
149 	/**
150 		To support hash based sharding, MongoDB provides a hashed index type,
151 		which indexes the hash of the value of a field. These indexes have a
152 		more random distribution of values along their range, but only support
153 		equality matches and cannot support range-based queries.
154 
155 		See_Also: $(LINK https://docs.mongodb.com/manual/core/index-hashed/)
156 	*/
157 	hashed = "hashed",
158 }
159 
160 /**
161 	See_Also: $(LINK https://docs.mongodb.com/manual/reference/command/createIndexes/)
162 
163 	Standards: $(LINK https://github.com/mongodb/specifications/blob/0c6e56141c867907aacf386e0cbe56d6562a0614/source/index-management.rst#common-api-components)
164 */
165 struct IndexOptions
166 {
167 	/**
168 		Specifying true directs MongoDB to build the index in the background.
169 		Background builds do not block operations on the collection.
170 		Since MongoDB 4.2 indices are built on the background by default.
171 		In MongoDB 4.0 and before, this defaults to `false`.
172 	*/
173 	@embedNullable @until(WireVersion.v42)
174 	Nullable!bool background;
175 
176 	/**
177 		Specifies the length in time, in seconds, for documents to remain in a
178 		collection.
179 	*/
180 	@embedNullable Nullable!int expireAfterSeconds;
181 
182 	void expireAfter(Duration d)
183 	@safe {
184 		expireAfterSeconds = cast(int)d.total!"seconds";
185 	}
186 
187 	/**
188 		Optionally specify a specific name for the index outside of the default
189 		generated name. If none is provided then the name is generated in the
190 		format "[field]_[direction]"
191 	*/
192 	@ignore string name;
193 
194 	/**
195 		Tells the index to only reference documents with the specified field in
196 		the index.
197 	*/
198 	@embedNullable Nullable!bool sparse;
199 
200 	/**
201 		Allows configuring the storage engine on a per-index basis.
202 	*/
203 	@embedNullable @since(WireVersion.v30)
204 	Nullable!Bson storageEngine;
205 
206 	/**
207 		Forces the index to be unique.
208 	*/
209 	@embedNullable Nullable!bool unique;
210 
211 	/**
212 		Creates a unique index on a field that may have duplicates.
213 	*/
214 	@embedNullable @until(WireVersion.v26)
215 	Nullable!bool dropDups;
216 
217 	/**
218 		Specifies the index version number, either 0 or 1.
219 	*/
220 	@embedNullable @(.name("v")) @until(WireVersion.v26)
221 	Nullable!int version_;
222 
223 	/**
224 		Default language for text indexes. Is "english" if none is provided.
225 	*/
226 	@embedNullable @(.name("default_language"))
227 	Nullable!string defaultLanguage;
228 
229 	/**
230 		Specifies the field in the document to override the language.
231 	*/
232 	@embedNullable @(.name("language_override"))
233 	Nullable!string languageOverride;
234 
235 	/**
236 		Sets the text index version number.
237 
238 		MongoDB 2.4 can only support version 1.
239 
240 		MongoDB 2.6 and higher may support version 1 or 2.
241 	*/
242 	@embedNullable @since(WireVersion.v26)
243 	Nullable!int textIndexVersion;
244 
245 	/**
246 		Specifies fields in the index and their corresponding weight values.
247 	*/
248 	@embedNullable Nullable!Bson weights;
249 
250 	/**
251 		Sets the 2dsphere index version number.
252 
253 		MongoDB 2.4 can only support version 1.
254 
255 		MongoDB 2.6 and higher may support version 1 or 2.
256 
257 		MongoDB 3.2 and higher may support version 2 or 3.
258 	*/
259 	@embedNullable @(.name("2dsphereIndexVersion")) @since(WireVersion.v26)
260 	Nullable!int _2dsphereIndexVersion;
261 
262 	/**
263 		For 2d indexes, the number of precision of the stored geo hash value of
264 		the location data.
265 	*/
266 	@embedNullable Nullable!int bits;
267 
268 	/**
269 		For 2d indexes, the upper inclusive boundary for the longitude and
270 		latitude values.
271 	*/
272 	@embedNullable Nullable!double max;
273 
274 	/**
275 		For 2d indexes, the lower inclusive boundary for the longitude and
276 		latitude values.
277 	*/
278 	@embedNullable Nullable!double min;
279 
280 	/**
281 		For geoHaystack indexes, specify the number of units within which to
282 		group the location values; i.e. group in the same bucket those location
283 		values that are within the specified number of units to each other.
284 
285 		The value must be greater than 0.
286 	*/
287 	@embedNullable Nullable!double bucketSize;
288 
289 	/**
290 		If specified, the index only references documents that match the filter
291 		expression. See
292 		$(LINK2 https://docs.mongodb.com/manual/core/index-partial/, Partial Indexes)
293 		for more information.
294 	*/
295 	@embedNullable @since(WireVersion.v32)
296 	Nullable!Bson partialFilterExpression;
297 
298 	/**
299 		Collation allows users to specify language-specific rules for string
300 		comparison, such as rules for letter-case and accent marks.
301 	*/
302 	@embedNullable @since(WireVersion.v34)
303 	Nullable!Collation collation;
304 
305 	/**
306 		Allows users to include or exclude specific field paths from a wildcard
307 		index using the `{ "$**": 1 }` key pattern.
308 	*/
309 	@embedNullable @since(WireVersion.v42)
310 	Nullable!Bson wildcardProjection;
311 }
312 
313 /// Standards: $(LINK https://github.com/mongodb/specifications/blob/0c6e56141c867907aacf386e0cbe56d6562a0614/source/index-management.rst#common-api-components)
314 struct CreateIndexOptions
315 {
316 	/**
317 		The maximum amount of time to allow the index build to take before
318 		returning an error. (not implemented)
319 	*/
320 	@embedNullable Nullable!long maxTimeMS;
321 }
322 
323 /// Same as $(LREF CreateIndexOptions)
324 alias CreateIndexesOptions = CreateIndexOptions;
325 
326 /// Standards: $(LINK https://github.com/mongodb/specifications/blob/f4020bdb6ec093fcd259984e6ff6f42356b17d0e/source/index-management.rst#standard-api)
327 struct DropIndexOptions
328 {
329 	/**
330 		The maximum amount of time to allow the index drop to take before
331 		returning an error. (not implemented)
332 	*/
333 	@embedNullable Nullable!long maxTimeMS;
334 }
335 
336 /// Same as $(LREF DropIndexOptions)
337 alias DropIndexesOptions = DropIndexOptions;