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 /// @note `std::nullopt` resets the operation override, allowing the pool default to apply.
56 ReadPreference& SetMaxStaleness(std::optional<std::chrono::seconds> max_staleness);
57
58 /// @brief Adds a tag to the tag set.
59 /// @note Cannot be used with kPrimary mode.
61
62private:
63 Mode mode_;
64 std::optional<std::chrono::seconds> max_staleness_;
65 std::vector<formats::bson::Document> tags_;
66};
67
68/// @brief Read concern
69/// @see https://docs.mongodb.org/manual/reference/readConcern/
70enum class ReadConcern {
71 /// no replication checks, default level
73 /// return data replicated to a majority of RS members
75 /// waits for all running majority writes to finish before read
77 /// no replication checks, may return orphaned documents if sharded; since 3.6
79};
80
81/// @brief Write concern
82/// @see https://docs.mongodb.org/manual/reference/write-concern/
84public:
85 enum Level {
86 /// Wait until propagation to a "majority" of RS nodes
88 /// Do not check for operation errors, do not wait for write, same as `0`
90 };
91
92 /// Default timeout for "majority" write concern
93 static constexpr std::chrono::seconds kDefaultMajorityTimeout{1};
94
95 /// Creates a write concern with the special level
96 explicit WriteConcern(Level level);
97
98 /// Creates a write concern waiting for propagation to `nodes_count` RS nodes
99 explicit WriteConcern(size_t nodes_count);
100
101 /// Creates a write concern defined in RS config
102 explicit WriteConcern(std::string tag);
103
104 bool IsMajority() const;
105 size_t NodesCount() const;
106 const std::string& Tag() const;
107 std::optional<bool> Journal() const;
108 const std::chrono::milliseconds& Timeout() const;
109
110 /// Sets write concern timeout, `0` means no timeout
111 WriteConcern& SetTimeout(std::chrono::milliseconds timeout);
112
113 /// Sets whether to wait for on-disk journal commit
115
116private:
117 size_t nodes_count_;
118 bool is_majority_;
119 std::optional<bool> journal_;
120 std::string tag_;
121 std::chrono::milliseconds timeout_;
122};
123
124/// Disables ordering on bulk operations causing them to continue after an error
125class Unordered {};
126
127/// Enables insertion of a new document when update selector matches nothing
128class Upsert {};
129
130/// Enables automatic one-time retry of duplicate key errors
132
133/// Specifies that FindAndModify should return the new version of an object
134class ReturnNew {};
135
136/// Specifies the number of documents to skip
137class Skip {
138public:
139 constexpr explicit Skip(size_t value)
140 : value_(value)
141 {}
142
143 size_t Value() const { return value_; }
144
145private:
146 size_t value_;
147};
148
149/// @brief Specifies the number of documents to request from the server
150/// @note The value of `0` means "no limit".
151class Limit {
152public:
153 constexpr explicit Limit(size_t value)
154 : value_(value)
155 {}
156
157 size_t Value() const { return value_; }
158
159private:
160 size_t value_;
161};
162
163/// @brief Specifies the number of documents per wire-protocol batch.
164/// Controls both the initial find batch and subsequent getMore batches.
165/// @note The value of `0` means "use server default".
167public:
168 explicit BatchSize(size_t value)
169 : value_(value)
170 {}
171
172 size_t Value() const { return value_; }
173
174private:
175 size_t value_;
176};
177
178/// @brief Selects fields to be returned
179/// @note `_id` field is always included by default, order might be significant
180/// @see
181/// https://docs.mongodb.com/manual/tutorial/project-fields-from-query-results/
183public:
184 /// Creates a default projection including all fields
185 Projection() = default;
186
187 /// Creates a projection including only specified fields
188 Projection(std::initializer_list<std::string_view> fields_to_include);
189
190 /// Includes a field into the projection
191 Projection& Include(std::string_view field);
192
193 /// @brief Excludes a field from the projection
194 /// @warning Projection cannot have a mix of inclusion and exclusion.
195 /// Only the `_id` field can always be excluded.
196 Projection& Exclude(std::string_view field);
197
198 /// @brief Setups an array slice in the projection
199 /// @param field name of the array field to slice
200 /// @param limit the number of items to return
201 /// @param skip the following number of items
202 /// @note `skip` can be negative, this corresponds to counting from the end
203 /// backwards.
204 /// @note `limit < 0, skip == 0` is equivalent to `limit' = -limit, skip' =
205 /// limit`.
206 /// @warning Cannot be applied to views.
207 Projection& Slice(std::string_view field, int32_t limit, int32_t skip = 0);
208
209 /// @brief Matches the first element of an array satisfying a predicate
210 /// @param field name of the array to search
211 /// @param pred predicate to apply to elements
212 /// @note Array field will be absent from the result if no elements match.
213 /// @note Empty document as a predicate will only match empty documents.
214 Projection& ElemMatch(std::string_view field, const formats::bson::Document& pred);
215
216 /// @cond
217 /// Projection specification BSON access
218 const bson_t* GetProjectionBson() const;
219 /// @endcond
220
221private:
222 formats::bson::impl::BsonBuilder projection_builder_;
223};
224
225/// Sorts the results
226class Sort {
227public:
228 enum Direction {
229 kAscending,
230 kDescending,
231 };
232
233 /// Creates an empty ordering specification
234 Sort() = default;
235
236 /// Stores the specified ordering specification
237 Sort(std::initializer_list<std::pair<std::string_view, Direction>>);
238
239 /// Appends a field to the ordering specification
240 Sort& By(std::string_view field, Direction direction);
241
242 /// @cond
243 /// Sort specification BSON access
244 const bson_t* GetSortBson() const;
245 /// @endcond
246
247private:
248 formats::bson::impl::BsonBuilder sort_builder_;
249};
250
251/// @brief Specifies an index to use for the query
252/// @warning Only plans using the index will be considered.
253class Hint {
254public:
255 /// Specifies an index by name
256 explicit Hint(std::string index_name);
257
258 /// Specifies an index by fields covered
259 explicit Hint(formats::bson::Document index_spec);
260
261 /// @cond
262 /// Retrieves a hint value
263 const formats::bson::Value& Value() const;
264 /// @endcond
265
266private:
267 formats::bson::Value value_;
268};
269
270/// @brief Specifies an array of filter documents that
271/// determine which array elements to modify for an update
272/// operation on an array field.
274public:
275 /// Specifies list of filters
276 explicit ArrayFilters(std::initializer_list<formats::bson::Document>);
277
278 /// Specifies list of filters by container iterators
279 template <typename Iterator>
280 requires std::is_convertible_v<typename std::iterator_traits<Iterator>::value_type, formats::bson::Document>
281 ArrayFilters(Iterator first, Iterator last) {
282 formats::bson::ValueBuilder builder{formats::common::Type::kArray};
283 for (auto it = first; it != last; ++it) {
284 builder.PushBack(*it);
285 }
286 value_ = builder.ExtractValue();
287 }
288
289 /// @cond
290 /// Retrieves an arrayFilters value
291 const formats::bson::Value& Value() const;
292 /// @endcond
293
294private:
295 formats::bson::Value value_;
296};
297
298/// Suppresses errors on querying a sharded collection with unavailable shards
300
301/// @brief Disables exception throw on server errors, should be checked manually
302/// in WriteResult
303/// @note Always check the OperationError method in WriteResult. If the error is not empty,
304/// then there is a possibility that the bulk was not fully executed.
306
307/// @brief Enables tailable cursor, which block at the end of capped collections
308/// @note Automatically sets `awaitData`.
309/// @see https://docs.mongodb.com/manual/core/tailable-cursors/
310class Tailable {};
311
312/// Sets a comment for the operation, which would be visible in profile data
313class Comment {
314public:
315 explicit Comment(std::string);
316
317 const std::string& Value() const;
318
319private:
320 std::string value_;
321};
322
323/// @brief Specifies the server-side time limit for the operation
324/// @warning This does not set any client-side timeouts.
326public:
327 constexpr explicit MaxServerTime(const std::chrono::milliseconds& value)
328 : value_(value)
329 {}
330
331 const std::chrono::milliseconds& Value() const { return value_; }
332
333private:
334 std::chrono::milliseconds value_;
335};
336
337/// @brief Specifies collation options for text comparison
338/// @see https://docs.mongodb.com/manual/reference/collation/
339/// @see https://unicode-org.github.io/icu/userguide/collation/concepts.html
340class Collation final {
341public:
342 enum class Strength {
343 /// Primary level of comparison (base characters only)
345 /// Secondary level (base characters + diacritics)
347 /// Tertiary level (base + diacritics + case), default
349 /// Quaternary level
351 /// Identical level (tie breaker)
353 };
354
355 enum class CaseFirst {
356 /// Default value, similar to lower with slight differences
358 /// Uppercase sorts before lowercase
360 /// Lowercase sorts before uppercase
362 };
363
364 enum class Alternate {
365 /// Whitespace and punctuation are considered base characters (default)
367 /// Whitespace and punctuation not considered base characters
369 };
370
371 enum class MaxVariable {
372 /// Both whitespace and punctuation are ignorable
374 /// Only whitespace is ignorable
376 };
377
378 /// Creates a collation with mandatory locale
379 explicit Collation(std::string locale);
380
381 /// @brief Sets the ICU collation level
382 /// Default is kTertiary
383 Collation& SetStrength(Strength strength);
384
385 /// @brief Sets whether to include case comparison at strength level 1 or 2
386 /// Default is false
387 Collation& SetCaseLevel(bool case_level);
388
389 /// @brief Sets sort order of case differences during tertiary level comparisons
390 /// Default is kOff
391 Collation& SetCaseFirst(CaseFirst case_first);
392
393 /// @brief Sets whether to compare numeric strings as numbers or as strings
394 /// Default is false (compare as strings)
395 Collation& SetNumericOrdering(bool numeric_ordering);
396
397 /// @brief Sets whether collation should consider whitespace and punctuation as base characters
398 /// Default is kNonIgnorable
399 Collation& SetAlternate(Alternate alternate);
400
401 /// @brief Sets up to which characters are considered ignorable when alternate is kShifted
402 /// Has no effect if alternate is kNonIgnorable
403 Collation& SetMaxVariable(MaxVariable max_variable);
404
405 /// @brief Sets whether strings with diacritics sort from back of the string
406 /// Default is false (compare from front to back)
407 Collation& SetBackwards(bool backwards);
408
409 /// @brief Sets whether to check if text require normalization and perform normalization
410 /// Default is false
411 Collation& SetNormalization(bool normalization);
412
413 /// @cond
414 /// Collation specification BSON access for internal use
415 const bson_t* GetCollationBson() const;
416 /// @endcond
417
418private:
419 formats::bson::impl::BsonBuilder collation_builder_;
420};
421
422} // namespace storages::mongo::options
423
424USERVER_NAMESPACE_END