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