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) : value_(value) {}
139
140 size_t Value() const { return value_; }
141
142private:
143 size_t value_;
144};
145
146/// @brief Specifies the number of documents to request from the server
147/// @note The value of `0` means "no limit".
148class Limit {
149public:
150 explicit Limit(size_t value) : value_(value) {}
151
152 size_t Value() const { return value_; }
153
154private:
155 size_t value_;
156};
157
158/// @brief Selects fields to be returned
159/// @note `_id` field is always included by default, order might be significant
160/// @see
161/// https://docs.mongodb.com/manual/tutorial/project-fields-from-query-results/
163public:
164 /// Creates a default projection including all fields
165 Projection() = default;
166
167 /// Creates a projection including only specified fields
168 Projection(std::initializer_list<std::string_view> fields_to_include);
169
170 /// Includes a field into the projection
171 Projection& Include(std::string_view field);
172
173 /// @brief Excludes a field from the projection
174 /// @warning Projection cannot have a mix of inclusion and exclusion.
175 /// Only the `_id` field can always be excluded.
176 Projection& Exclude(std::string_view field);
177
178 /// @brief Setups an array slice in the projection
179 /// @param field name of the array field to slice
180 /// @param limit the number of items to return
181 /// @param skip the following number of items
182 /// @note `skip` can be negative, this corresponds to counting from the end
183 /// backwards.
184 /// @note `limit < 0, skip == 0` is equivalent to `limit' = -limit, skip' =
185 /// limit`.
186 /// @warning Cannot be applied to views.
187 Projection& Slice(std::string_view field, int32_t limit, int32_t skip = 0);
188
189 /// @brief Matches the first element of an array satisfying a predicate
190 /// @param field name of the array to search
191 /// @param pred predicate to apply to elements
192 /// @note Array field will be absent from the result if no elements match.
193 /// @note Empty document as a predicate will only match empty documents.
194 Projection& ElemMatch(std::string_view field, const formats::bson::Document& pred);
195
196 /// @cond
197 /// Projection specification BSON access
198 const bson_t* GetProjectionBson() const;
199 /// @endcond
200
201private:
202 formats::bson::impl::BsonBuilder projection_builder_;
203};
204
205/// Sorts the results
206class Sort {
207public:
208 enum Direction {
209 kAscending,
210 kDescending,
211 };
212
213 /// Creates an empty ordering specification
214 Sort() = default;
215
216 /// Stores the specified ordering specification
217 Sort(std::initializer_list<std::pair<std::string_view, Direction>>);
218
219 /// Appends a field to the ordering specification
220 Sort& By(std::string_view field, Direction direction);
221
222 /// @cond
223 /// Sort specification BSON access
224 const bson_t* GetSortBson() const;
225 /// @endcond
226
227private:
228 formats::bson::impl::BsonBuilder sort_builder_;
229};
230
231/// @brief Specifies an index to use for the query
232/// @warning Only plans using the index will be considered.
233class Hint {
234public:
235 /// Specifies an index by name
236 explicit Hint(std::string index_name);
237
238 /// Specifies an index by fields covered
239 explicit Hint(formats::bson::Document index_spec);
240
241 /// @cond
242 /// Retrieves a hint value
243 const formats::bson::Value& Value() const;
244 /// @endcond
245
246private:
247 formats::bson::Value value_;
248};
249
250/// @brief Specifies an array of filter documents that
251/// determine which array elements to modify for an update
252/// operation on an array field.
254public:
255 /// Specifies list of filters
256 explicit ArrayFilters(std::initializer_list<formats::bson::Document>);
257
258 /// Specifies list of filters by container iterators
259 template <
260 typename Iterator,
261 typename = std::enable_if_t<
262 std::is_convertible_v<typename std::iterator_traits<Iterator>::value_type, formats::bson::Document>>>
263 ArrayFilters(Iterator first, Iterator last) {
265 for (auto it = first; it != last; ++it) {
266 builder.PushBack(*it);
267 }
268 value_ = builder.ExtractValue();
269 }
270
271 /// @cond
272 /// Retrieves an arrayFilters value
273 const formats::bson::Value& Value() const;
274 /// @endcond
275
276private:
277 formats::bson::Value value_;
278};
279
280/// Suppresses errors on querying a sharded collection with unavailable shards
282
283/// @brief Disables exception throw on server errors, should be checked manually
284/// in WriteResult
286
287/// @brief Enables tailable cursor, which block at the end of capped collections
288/// @note Automatically sets `awaitData`.
289/// @see https://docs.mongodb.com/manual/core/tailable-cursors/
290class Tailable {};
291
292/// Sets a comment for the operation, which would be visible in profile data
293class Comment {
294public:
295 explicit Comment(std::string);
296
297 const std::string& Value() const;
298
299private:
300 std::string value_;
301};
302
303/// @brief Specifies the server-side time limit for the operation
304/// @warning This does not set any client-side timeouts.
306public:
307 explicit MaxServerTime(const std::chrono::milliseconds& value) : value_(value) {}
308
309 const std::chrono::milliseconds& Value() const { return value_; }
310
311private:
312 std::chrono::milliseconds value_;
313};
314
315/// @brief Specifies collation options for text comparison
316/// @see https://docs.mongodb.com/manual/reference/collation/
317/// @see https://unicode-org.github.io/icu/userguide/collation/concepts.html
318class Collation final {
319public:
320 enum class Strength {
321 /// Primary level of comparison (base characters only)
323 /// Secondary level (base characters + diacritics)
325 /// Tertiary level (base + diacritics + case), default
327 /// Quaternary level
329 /// Identical level (tie breaker)
331 };
332
333 enum class CaseFirst {
334 /// Default value, similar to lower with slight differences
336 /// Uppercase sorts before lowercase
338 /// Lowercase sorts before uppercase
340 };
341
342 enum class Alternate {
343 /// Whitespace and punctuation are considered base characters (default)
345 /// Whitespace and punctuation not considered base characters
347 };
348
349 enum class MaxVariable {
350 /// Both whitespace and punctuation are ignorable
352 /// Only whitespace is ignorable
354 };
355
356 /// Creates a collation with mandatory locale
357 explicit Collation(std::string locale);
358
359 /// @brief Sets the ICU collation level
360 /// Default is kTertiary
361 Collation& SetStrength(Strength strength);
362
363 /// @brief Sets whether to include case comparison at strength level 1 or 2
364 /// Default is false
365 Collation& SetCaseLevel(bool case_level);
366
367 /// @brief Sets sort order of case differences during tertiary level comparisons
368 /// Default is kOff
369 Collation& SetCaseFirst(CaseFirst case_first);
370
371 /// @brief Sets whether to compare numeric strings as numbers or as strings
372 /// Default is false (compare as strings)
373 Collation& SetNumericOrdering(bool numeric_ordering);
374
375 /// @brief Sets whether collation should consider whitespace and punctuation as base characters
376 /// Default is kNonIgnorable
377 Collation& SetAlternate(Alternate alternate);
378
379 /// @brief Sets up to which characters are considered ignorable when alternate is kShifted
380 /// Has no effect if alternate is kNonIgnorable
381 Collation& SetMaxVariable(MaxVariable max_variable);
382
383 /// @brief Sets whether strings with diacritics sort from back of the string
384 /// Default is false (compare from front to back)
385 Collation& SetBackwards(bool backwards);
386
387 /// @brief Sets whether to check if text require normalization and perform normalization
388 /// Default is false
389 Collation& SetNormalization(bool normalization);
390
391 /// @cond
392 /// Collation specification BSON access for internal use
393 const bson_t* GetCollationBson() const;
394 /// @endcond
395
396private:
397 formats::bson::impl::BsonBuilder collation_builder_;
398};
399
400} // namespace storages::mongo::options
401
402USERVER_NAMESPACE_END