userver: userver/storages/mongo/options.hpp Source File
Loading...
Searching...
No Matches
options.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file userver/storages/mongo/options.hpp
4/// @brief Query options
5
6#include <chrono>
7#include <cstddef>
8#include <cstdint>
9#include <initializer_list>
10#include <optional>
11#include <string>
12#include <string_view>
13#include <utility>
14#include <vector>
15
16#include <userver/formats/bson/bson_builder.hpp>
17#include <userver/formats/bson/document.hpp>
18#include <userver/formats/bson/value.hpp>
19#include <userver/formats/bson/value_builder.hpp>
20#include <userver/formats/common/type.hpp>
21
22USERVER_NAMESPACE_BEGIN
23
24/// Collection operation options
25namespace storages::mongo::options {
26
27/// @brief Read preference
28/// @see https://github.com/mongodb/mongo-c-driver/blob/master/src/libmongoc/doc/mongoc_read_prefs_t.rst
30public:
31 enum Mode {
32 /// Default mode. All operations read from the current replica set primary.
34 /// All operations read from among the nearest secondary members of the replica set.
36 /// In most situations, operations read from the primary but if it is unavailable, operations read from
37 /// secondary members.
39 /// In most situations, operations read from among the nearest secondary members, but if no secondaries are
40 /// available, operations read from the primary.
42 /// Operations read from among the nearest members of the replica set, irrespective of the member's type.
44 };
45
46 explicit ReadPreference(Mode mode);
47 ReadPreference(Mode mode, std::vector<formats::bson::Document> tags);
48
49 Mode GetMode() const;
50 std::optional<std::chrono::seconds> GetMaxStaleness() const;
51 const std::vector<formats::bson::Document>& GetTags() const;
52
53 /// @brief Sets maximum replication lag for eligible replica.
54 /// @note Must be at least 90 seconds, cannot be used with kPrimary mode.
55 ReadPreference& SetMaxStaleness(std::optional<std::chrono::seconds> max_staleness);
56
57 /// @brief Adds a tag to the tag set.
58 /// @note Cannot be used with kPrimary mode.
60
61private:
62 Mode mode_;
63 std::optional<std::chrono::seconds> max_staleness_;
64 std::vector<formats::bson::Document> tags_;
65};
66
67/// @brief Read concern
68/// @see https://docs.mongodb.org/manual/reference/readConcern/
69enum class ReadConcern {
70 /// no replication checks, default level
72 /// return data replicated to a majority of RS members
74 /// waits for all running majority writes to finish before read
76 /// no replication checks, may return orphaned documents if sharded; since 3.6
78};
79
80/// @brief Write concern
81/// @see https://docs.mongodb.org/manual/reference/write-concern/
83public:
84 enum Level {
85 /// Wait until propagation to a "majority" of RS nodes
87 /// Do not check for operation errors, do not wait for write, same as `0`
89 };
90
91 /// Default timeout for "majority" write concern
92 static constexpr std::chrono::seconds kDefaultMajorityTimeout{1};
93
94 /// Creates a write concern with the special level
95 explicit WriteConcern(Level level);
96
97 /// Creates a write concern waiting for propagation to `nodes_count` RS nodes
98 explicit WriteConcern(size_t nodes_count);
99
100 /// Creates a write concern defined in RS config
101 explicit WriteConcern(std::string tag);
102
103 bool IsMajority() const;
104 size_t NodesCount() const;
105 const std::string& Tag() const;
106 std::optional<bool> Journal() const;
107 const std::chrono::milliseconds& Timeout() const;
108
109 /// Sets write concern timeout, `0` means no timeout
110 WriteConcern& SetTimeout(std::chrono::milliseconds timeout);
111
112 /// Sets whether to wait for on-disk journal commit
114
115private:
116 size_t nodes_count_;
117 bool is_majority_;
118 std::optional<bool> journal_;
119 std::string tag_;
120 std::chrono::milliseconds timeout_;
121};
122
123/// Disables ordering on bulk operations causing them to continue after an error
124class Unordered {};
125
126/// Enables insertion of a new document when update selector matches nothing
127class Upsert {};
128
129/// Enables automatic one-time retry of duplicate key errors
131
132/// Specifies that FindAndModify should return the new version of an object
133class ReturnNew {};
134
135/// Specifies the number of documents to skip
136class Skip {
137public:
138 explicit Skip(size_t value)
139 : value_(value)
140 {}
141
142 size_t Value() const { return value_; }
143
144private:
145 size_t value_;
146};
147
148/// @brief Specifies the number of documents to request from the server
149/// @note The value of `0` means "no limit".
150class Limit {
151public:
152 explicit Limit(size_t value)
153 : value_(value)
154 {}
155
156 size_t Value() const { return value_; }
157
158private:
159 size_t value_;
160};
161
162/// @brief Selects fields to be returned
163/// @note `_id` field is always included by default, order might be significant
164/// @see
165/// https://docs.mongodb.com/manual/tutorial/project-fields-from-query-results/
167public:
168 /// Creates a default projection including all fields
169 Projection() = default;
170
171 /// Creates a projection including only specified fields
172 Projection(std::initializer_list<std::string_view> fields_to_include);
173
174 /// Includes a field into the projection
175 Projection& Include(std::string_view field);
176
177 /// @brief Excludes a field from the projection
178 /// @warning Projection cannot have a mix of inclusion and exclusion.
179 /// Only the `_id` field can always be excluded.
180 Projection& Exclude(std::string_view field);
181
182 /// @brief Setups an array slice in the projection
183 /// @param field name of the array field to slice
184 /// @param limit the number of items to return
185 /// @param skip the following number of items
186 /// @note `skip` can be negative, this corresponds to counting from the end
187 /// backwards.
188 /// @note `limit < 0, skip == 0` is equivalent to `limit' = -limit, skip' =
189 /// limit`.
190 /// @warning Cannot be applied to views.
191 Projection& Slice(std::string_view field, int32_t limit, int32_t skip = 0);
192
193 /// @brief Matches the first element of an array satisfying a predicate
194 /// @param field name of the array to search
195 /// @param pred predicate to apply to elements
196 /// @note Array field will be absent from the result if no elements match.
197 /// @note Empty document as a predicate will only match empty documents.
198 Projection& ElemMatch(std::string_view field, const formats::bson::Document& pred);
199
200 /// @cond
201 /// Projection specification BSON access
202 const bson_t* GetProjectionBson() const;
203 /// @endcond
204
205private:
206 formats::bson::impl::BsonBuilder projection_builder_;
207};
208
209/// Sorts the results
210class Sort {
211public:
212 enum Direction {
213 kAscending,
214 kDescending,
215 };
216
217 /// Creates an empty ordering specification
218 Sort() = default;
219
220 /// Stores the specified ordering specification
221 Sort(std::initializer_list<std::pair<std::string_view, Direction>>);
222
223 /// Appends a field to the ordering specification
224 Sort& By(std::string_view field, Direction direction);
225
226 /// @cond
227 /// Sort specification BSON access
228 const bson_t* GetSortBson() const;
229 /// @endcond
230
231private:
232 formats::bson::impl::BsonBuilder sort_builder_;
233};
234
235/// @brief Specifies an index to use for the query
236/// @warning Only plans using the index will be considered.
237class Hint {
238public:
239 /// Specifies an index by name
240 explicit Hint(std::string index_name);
241
242 /// Specifies an index by fields covered
243 explicit Hint(formats::bson::Document index_spec);
244
245 /// @cond
246 /// Retrieves a hint value
247 const formats::bson::Value& Value() const;
248 /// @endcond
249
250private:
251 formats::bson::Value value_;
252};
253
254/// @brief Specifies an array of filter documents that
255/// determine which array elements to modify for an update
256/// operation on an array field.
258public:
259 /// Specifies list of filters
260 explicit ArrayFilters(std::initializer_list<formats::bson::Document>);
261
262 /// Specifies list of filters by container iterators
263 template <
264 typename Iterator,
265 typename = std::enable_if_t<
266 std::is_convertible_v<typename std::iterator_traits<Iterator>::value_type, formats::bson::Document>>>
267 ArrayFilters(Iterator first, Iterator last) {
269 for (auto it = first; it != last; ++it) {
270 builder.PushBack(*it);
271 }
272 value_ = builder.ExtractValue();
273 }
274
275 /// @cond
276 /// Retrieves an arrayFilters value
277 const formats::bson::Value& Value() const;
278 /// @endcond
279
280private:
281 formats::bson::Value value_;
282};
283
284/// Suppresses errors on querying a sharded collection with unavailable shards
286
287/// @brief Disables exception throw on server errors, should be checked manually
288/// in WriteResult
290
291/// @brief Enables tailable cursor, which block at the end of capped collections
292/// @note Automatically sets `awaitData`.
293/// @see https://docs.mongodb.com/manual/core/tailable-cursors/
294class Tailable {};
295
296/// Sets a comment for the operation, which would be visible in profile data
297class Comment {
298public:
299 explicit Comment(std::string);
300
301 const std::string& Value() const;
302
303private:
304 std::string value_;
305};
306
307/// @brief Specifies the server-side time limit for the operation
308/// @warning This does not set any client-side timeouts.
310public:
311 explicit MaxServerTime(const std::chrono::milliseconds& value)
312 : value_(value)
313 {}
314
315 const std::chrono::milliseconds& Value() const { return value_; }
316
317private:
318 std::chrono::milliseconds value_;
319};
320
321/// @brief Specifies collation options for text comparison
322/// @see https://docs.mongodb.com/manual/reference/collation/
323/// @see https://unicode-org.github.io/icu/userguide/collation/concepts.html
324class Collation final {
325public:
326 enum class Strength {
327 /// Primary level of comparison (base characters only)
329 /// Secondary level (base characters + diacritics)
331 /// Tertiary level (base + diacritics + case), default
333 /// Quaternary level
335 /// Identical level (tie breaker)
337 };
338
339 enum class CaseFirst {
340 /// Default value, similar to lower with slight differences
342 /// Uppercase sorts before lowercase
344 /// Lowercase sorts before uppercase
346 };
347
348 enum class Alternate {
349 /// Whitespace and punctuation are considered base characters (default)
351 /// Whitespace and punctuation not considered base characters
353 };
354
355 enum class MaxVariable {
356 /// Both whitespace and punctuation are ignorable
358 /// Only whitespace is ignorable
360 };
361
362 /// Creates a collation with mandatory locale
363 explicit Collation(std::string locale);
364
365 /// @brief Sets the ICU collation level
366 /// Default is kTertiary
367 Collation& SetStrength(Strength strength);
368
369 /// @brief Sets whether to include case comparison at strength level 1 or 2
370 /// Default is false
371 Collation& SetCaseLevel(bool case_level);
372
373 /// @brief Sets sort order of case differences during tertiary level comparisons
374 /// Default is kOff
375 Collation& SetCaseFirst(CaseFirst case_first);
376
377 /// @brief Sets whether to compare numeric strings as numbers or as strings
378 /// Default is false (compare as strings)
379 Collation& SetNumericOrdering(bool numeric_ordering);
380
381 /// @brief Sets whether collation should consider whitespace and punctuation as base characters
382 /// Default is kNonIgnorable
383 Collation& SetAlternate(Alternate alternate);
384
385 /// @brief Sets up to which characters are considered ignorable when alternate is kShifted
386 /// Has no effect if alternate is kNonIgnorable
387 Collation& SetMaxVariable(MaxVariable max_variable);
388
389 /// @brief Sets whether strings with diacritics sort from back of the string
390 /// Default is false (compare from front to back)
391 Collation& SetBackwards(bool backwards);
392
393 /// @brief Sets whether to check if text require normalization and perform normalization
394 /// Default is false
395 Collation& SetNormalization(bool normalization);
396
397 /// @cond
398 /// Collation specification BSON access for internal use
399 const bson_t* GetCollationBson() const;
400 /// @endcond
401
402private:
403 formats::bson::impl::BsonBuilder collation_builder_;
404};
405
406} // namespace storages::mongo::options
407
408USERVER_NAMESPACE_END