userver: userver/storages/mongo/options.hpp Source File
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages Concepts
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
142 size_t value_;
143};
144
145/// @brief Specifies the number of documents to request from the server
146/// @note The value of `0` means "no limit".
147class Limit {
148public:
149 explicit Limit(size_t value) : value_(value) {}
150
151 size_t Value() const { return value_; }
152
153private:
154 size_t value_;
155};
156
157/// @brief Selects fields to be returned
158/// @note `_id` field is always included by default, order might be significant
159/// @see
160/// https://docs.mongodb.com/manual/tutorial/project-fields-from-query-results/
162public:
163 /// Creates a default projection including all fields
164 Projection() = default;
165
166 /// Creates a projection including only specified fields
167 Projection(std::initializer_list<std::string_view> fields_to_include);
168
169 /// Includes a field into the projection
170 Projection& Include(std::string_view field);
171
172 /// @brief Excludes a field from the projection
173 /// @warning Projection cannot have a mix of inclusion and exclusion.
174 /// Only the `_id` field can always be excluded.
175 Projection& Exclude(std::string_view field);
176
177 /// @brief Setups an array slice in the projection
178 /// @param field name of the array field to slice
179 /// @param limit the number of items to return
180 /// @param skip the following number of items
181 /// @note `skip` can be negative, this corresponds to counting from the end
182 /// backwards.
183 /// @note `limit < 0, skip == 0` is equivalent to `limit' = -limit, skip' =
184 /// limit`.
185 /// @warning Cannot be applied to views.
186 Projection& Slice(std::string_view field, int32_t limit, int32_t skip = 0);
187
188 /// @brief Matches the first element of an array satisfying a predicate
189 /// @param field name of the array to search
190 /// @param pred predicate to apply to elements
191 /// @note Array field will be absent from the result if no elements match.
192 /// @note Empty document as a predicate will only match empty documents.
193 Projection& ElemMatch(std::string_view field, const formats::bson::Document& pred);
194
195 /// @cond
196 /// Projection specification BSON access
197 const bson_t* GetProjectionBson() const;
198 /// @endcond
199
200private:
201 formats::bson::impl::BsonBuilder projection_builder_;
202};
203
204/// Sorts the results
205class Sort {
206public:
207 enum Direction {
208 kAscending,
209 kDescending,
210 };
211
212 /// Creates an empty ordering specification
213 Sort() = default;
214
215 /// Stores the specified ordering specification
216 Sort(std::initializer_list<std::pair<std::string_view, Direction>>);
217
218 /// Appends a field to the ordering specification
219 Sort& By(std::string_view field, Direction direction);
220
221 /// @cond
222 /// Sort specification BSON access
223 const bson_t* GetSortBson() const;
224 /// @endcond
225
226private:
227 formats::bson::impl::BsonBuilder sort_builder_;
228};
229
230/// @brief Specifies an index to use for the query
231/// @warning Only plans using the index will be considered.
232class Hint {
233public:
234 /// Specifies an index by name
235 explicit Hint(std::string index_name);
236
237 /// Specifies an index by fields covered
238 explicit Hint(formats::bson::Document index_spec);
239
240 /// @cond
241 /// Retrieves a hint value
242 const formats::bson::Value& Value() const;
243 /// @endcond
244
245private:
246 formats::bson::Value value_;
247};
248
249/// @brief Specifies an array of filter documents that
250/// determine which array elements to modify for an update
251/// operation on an array field.
253public:
254 /// Specifies list of filters
255 explicit ArrayFilters(std::initializer_list<formats::bson::Document>);
256
257 /// Specifies list of filters by container iterators
258 template <
259 typename Iterator,
260 typename = std::enable_if_t<
261 std::is_convertible_v<typename std::iterator_traits<Iterator>::value_type, formats::bson::Document>>>
262 ArrayFilters(Iterator first, Iterator last) {
264 for (auto it = first; it != last; ++it) {
265 builder.PushBack(*it);
266 }
267 value_ = builder.ExtractValue();
268 }
269
270 /// @cond
271 /// Retrieves an arrayFilters value
272 const formats::bson::Value& Value() const;
273 /// @endcond
274
275private:
276 formats::bson::Value value_;
277};
278
279/// Selects count implementation to use: new aggregation-based or old cmd-based
280enum class ForceCountImpl { kAggregate, kCmd };
281
282/// Suppresses errors on querying a sharded collection with unavailable shards
284
285/// @brief Disables exception throw on server errors, should be checked manually
286/// in WriteResult
288
289/// @brief Enables tailable cursor, which block at the end of capped collections
290/// @note Automatically sets `awaitData`.
291/// @see https://docs.mongodb.com/manual/core/tailable-cursors/
292class Tailable {};
293
294/// Sets a comment for the operation, which would be visible in profile data
295class Comment {
296public:
297 explicit Comment(std::string);
298
299 const std::string& Value() const;
300
301private:
302 std::string value_;
303};
304
305/// @brief Specifies the server-side time limit for the operation
306/// @warning This does not set any client-side timeouts.
308public:
309 explicit MaxServerTime(const std::chrono::milliseconds& value) : value_(value) {}
310
311 const std::chrono::milliseconds& Value() const { return value_; }
312
313private:
314 std::chrono::milliseconds value_;
315};
316
317} // namespace storages::mongo::options
318
319USERVER_NAMESPACE_END