userver: userver/storages/mongo/collection.hpp Source File
Loading...
Searching...
No Matches
collection.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file userver/storages/mongo/collection.hpp
4/// @brief @copybrief storages::mongo::Collection
5
6#include <memory>
7#include <optional>
8#include <string>
9#include <type_traits>
10#include <vector>
11
12#include <userver/formats/bson/document.hpp>
13#include <userver/formats/bson/value.hpp>
14#include <userver/storages/mongo/bulk.hpp>
15#include <userver/storages/mongo/cursor.hpp>
16#include <userver/storages/mongo/operations.hpp>
17#include <userver/storages/mongo/write_result.hpp>
18#include <userver/utils/assert.hpp>
19
20USERVER_NAMESPACE_BEGIN
21
22namespace storages::mongo {
23
24namespace impl {
25class CollectionImpl;
26} // namespace impl
27
28/// @brief MongoDB collection handle, the main way to operate with MongoDB.
29///
30/// Usually retrieved from storages::mongo::Pool
31///
32/// ## Example:
33///
34/// @snippet storages/mongo/collection_mongotest.hpp Sample Mongo usage
36public:
37 /// @cond
38 // For internal use only.
39 explicit Collection(std::shared_ptr<impl::CollectionImpl>, bool transactional = false);
40 /// @endcond
41
42 /// @brief Returns the number of documents matching the query
43 /// @warning Unless explicitly overridden, runs CountApprox for empty filters
44 /// @see options::ForceCountImpl
45 template <typename... Options>
46 size_t Count(formats::bson::Document filter, Options&&... options) const;
47
48 /// @brief Returns an approximated count of all documents in the collection
49 /// @note This method uses collection metadata and should be faster
50 template <typename... Options>
51 size_t CountApprox(Options&&... options) const;
52
53 /// Performs a query on the collection
54 template <typename... Options>
55 Cursor Find(formats::bson::Document filter, Options&&... options) const;
56
57 /// Retrieves a single document from the collection
58 template <typename... Options>
59 std::optional<formats::bson::Document> FindOne(formats::bson::Document filter, Options&&... options) const;
60
61 /// Inserts a single document into the collection
62 template <typename... Options>
63 WriteResult InsertOne(formats::bson::Document document, Options&&... options);
64
65 /// Inserts multiple documents into the collection
66 template <typename... Options>
67 WriteResult InsertMany(std::vector<formats::bson::Document> documents, Options&&... options);
68
69 /// @brief Replaces a single matching document
70 /// @see options::Upsert
71 template <typename... Options>
72 WriteResult ReplaceOne(formats::bson::Document selector, formats::bson::Document replacement, Options&&... options);
73
74 /// @brief Updates a single matching document
75 /// @see options::Upsert
76 template <typename... Options>
77 WriteResult UpdateOne(formats::bson::Document selector, formats::bson::Document update, Options&&... options);
78
79 /// @brief Updates all matching documents
80 /// @see options::Upsert
81 template <typename... Options>
82 WriteResult UpdateMany(formats::bson::Document selector, formats::bson::Document update, Options&&... options);
83
84 /// Deletes a single matching document
85 template <typename... Options>
86 WriteResult DeleteOne(formats::bson::Document selector, Options&&... options);
87
88 /// Deletes all matching documents
89 template <typename... Options>
90 WriteResult DeleteMany(formats::bson::Document selector, Options&&... options);
91
92 /// @brief Atomically updates a single matching document
93 /// @see options::ReturnNew
94 /// @see options::Upsert
95 template <typename... Options>
97 formats::bson::Document query,
98 const formats::bson::Document& update,
99 Options&&... options
100 );
101
102 /// Atomically removes a single matching document
103 template <typename... Options>
104 WriteResult FindAndRemove(formats::bson::Document query, Options&&... options);
105
106 /// Drop collection
107 template <typename... Options>
108 void Drop(Options&&... options);
109
110 /// Efficiently executes multiple operations in order, stops on error
111 template <typename... Options>
112 operations::Bulk MakeOrderedBulk(Options&&... options);
113
114 /// Efficiently executes multiple operations out of order, continues on error
115 template <typename... Options>
116 operations::Bulk MakeUnorderedBulk(Options&&... options);
117
118 /// @brief Executes an aggregation pipeline
119 /// @param pipeline an array of aggregation operations
120 /// @param options see @ref storages::mongo::options
121 template <typename... Options>
122 Cursor Aggregate(formats::bson::Value pipeline, Options&&... options);
123
124 /// @brief Retrieves distinct values for a specified field
125 /// @param field name of the field for which to return distinct values
126 /// @param options see @ref storages::mongo::options
127 template <typename... Options>
128 std::vector<formats::bson::Value> Distinct(std::string field, Options&&... options) const;
129
130 /// @brief Retrieves distinct values for a specified field with a query filter
131 /// @param field name of the field for which to return distinct values
132 /// @param filter query that specifies the documents from which to retrieve distinct values
133 /// @param options see @ref storages::mongo::options
134 template <typename... Options>
135 std::vector<formats::bson::Value> Distinct(std::string field, formats::bson::Document filter, Options&&... options)
136 const;
137
138 /// Get collection name
139 const std::string& GetCollectionName() const;
140
141 /// @name Prepared operation executors
142 /// @{
143 size_t Execute(const operations::Count&) const;
144 size_t Execute(const operations::CountApprox&) const;
145 Cursor Execute(const operations::Find&) const;
146 std::vector<formats::bson::Value> Execute(const operations::Distinct&) const;
147 WriteResult Execute(const operations::InsertOne&);
148 WriteResult Execute(const operations::InsertMany&);
149 WriteResult Execute(const operations::ReplaceOne&);
150 WriteResult Execute(const operations::Update&);
151 WriteResult Execute(const operations::Delete&);
152 WriteResult Execute(const operations::FindAndModify&);
153 WriteResult Execute(const operations::FindAndRemove&);
154 WriteResult Execute(operations::Bulk&&);
155 Cursor Execute(const operations::Aggregate&);
156 void Execute(const operations::Drop&);
157 /// @}
158private:
159 std::shared_ptr<impl::CollectionImpl> impl_;
160 bool transactional_{false};
161};
162
163template <typename... Options>
164size_t Collection::Count(formats::bson::Document filter, Options&&... options) const {
165 operations::Count count_op(std::move(filter));
166 (count_op.SetOption(std::forward<Options>(options)), ...);
167 return Execute(count_op);
168}
169
170template <typename... Options>
171size_t Collection::CountApprox(Options&&... options) const {
172 operations::CountApprox count_approx_op;
173 (count_approx_op.SetOption(std::forward<Options>(options)), ...);
174 return Execute(count_approx_op);
175}
176
177namespace impl {
178
179template <typename Option, typename... Options>
180using HasOptionHelper = std::disjunction<std::is_same<std::decay_t<Options>, Option>...>;
181
182template <typename Option, typename... Options>
183static constexpr bool kHasOption = HasOptionHelper<Option, Options...>::value;
184
185} // namespace impl
186
187template <typename... Options>
188Cursor Collection::Find(formats::bson::Document filter, Options&&... options) const {
189 UINVARIANT(!transactional_, "Find is not supported for transaction collections");
190 operations::Find find_op(std::move(filter));
191 (find_op.SetOption(std::forward<Options>(options)), ...);
192 return Execute(find_op);
193}
194
195template <typename... Options>
196std::optional<formats::bson::Document> Collection::FindOne(formats::bson::Document filter, Options&&... options) const {
197 static_assert(
198 !(std::is_same<std::decay_t<Options>, options::Limit>::value || ...),
199 "Limit option cannot be used in FindOne"
200 );
201 operations::Find find_op(std::move(filter));
202 find_op.SetOption(options::Limit{1});
203 (find_op.SetOption(std::forward<Options>(options)), ...);
204 auto cursor = Execute(find_op);
205 if (cursor.begin() == cursor.end()) {
206 return {};
207 }
208 return *cursor.begin();
209}
210
211template <typename... Options>
212WriteResult Collection::InsertOne(formats::bson::Document document, Options&&... options) {
213 operations::InsertOne insert_op(std::move(document));
214 (insert_op.SetOption(std::forward<Options>(options)), ...);
215 return Execute(insert_op);
216}
217
218template <typename... Options>
219WriteResult Collection::InsertMany(std::vector<formats::bson::Document> documents, Options&&... options) {
220 operations::InsertMany insert_op(std::move(documents));
221 (insert_op.SetOption(std::forward<Options>(options)), ...);
222 return Execute(insert_op);
223}
224
225template <typename... Options>
227 formats::bson::Document selector,
228 formats::bson::Document replacement,
229 Options&&... options
230) {
231 operations::ReplaceOne replace_op(std::move(selector), std::move(replacement));
232 (replace_op.SetOption(std::forward<Options>(options)), ...);
233 return Execute(replace_op);
234}
235
236template <typename... Options>
238 formats::bson::Document selector,
239 formats::bson::Document update,
240 Options&&... options
241) {
242 operations::Update update_op(operations::Update::Mode::kSingle, std::move(selector), std::move(update));
243 (update_op.SetOption(std::forward<Options>(options)), ...);
244 return Execute(update_op);
245}
246
247template <typename... Options>
249 formats::bson::Document selector,
250 formats::bson::Document update,
251 Options&&... options
252) {
253 operations::Update update_op(operations::Update::Mode::kMulti, std::move(selector), std::move(update));
254 (update_op.SetOption(std::forward<Options>(options)), ...);
255 return Execute(update_op);
256}
257
258template <typename... Options>
259WriteResult Collection::DeleteOne(formats::bson::Document selector, Options&&... options) {
260 operations::Delete delete_op(operations::Delete::Mode::kSingle, std::move(selector));
261 (delete_op.SetOption(std::forward<Options>(options)), ...);
262 return Execute(delete_op);
263}
264
265template <typename... Options>
266WriteResult Collection::DeleteMany(formats::bson::Document selector, Options&&... options) {
267 operations::Delete delete_op(operations::Delete::Mode::kMulti, std::move(selector));
268 (delete_op.SetOption(std::forward<Options>(options)), ...);
269 return Execute(delete_op);
270}
271
272template <typename... Options>
274 formats::bson::Document query,
275 const formats::bson::Document& update,
276 Options&&... options
277) {
278 operations::FindAndModify fam_op(std::move(query), update);
279 (fam_op.SetOption(std::forward<Options>(options)), ...);
280 return Execute(fam_op);
281}
282
283template <typename... Options>
284WriteResult Collection::FindAndRemove(formats::bson::Document query, Options&&... options) {
285 operations::FindAndRemove fam_op(std::move(query));
286 (fam_op.SetOption(std::forward<Options>(options)), ...);
287 return Execute(fam_op);
288}
289
290template <typename... Options>
291void Collection::Drop(Options&&... options) {
292 operations::Drop drop_op;
293 (drop_op.SetOption(std::forward<Options>(options)), ...);
294 Execute(drop_op);
295}
296
297template <typename... Options>
298operations::Bulk Collection::MakeOrderedBulk(Options&&... options) {
299 operations::Bulk bulk(operations::Bulk::Mode::kOrdered);
300 (bulk.SetOption(std::forward<Options>(options)), ...);
301 return bulk;
302}
303
304template <typename... Options>
306 operations::Bulk bulk(operations::Bulk::Mode::kUnordered);
307 (bulk.SetOption(std::forward<Options>(options)), ...);
308 return bulk;
309}
310
311template <typename... Options>
312Cursor Collection::Aggregate(formats::bson::Value pipeline, Options&&... options) {
313 UINVARIANT(!transactional_, "Aggregate is not supported for transaction collections");
314 operations::Aggregate aggregate(std::move(pipeline));
315 (aggregate.SetOption(std::forward<Options>(options)), ...);
316 return Execute(aggregate);
317}
318
319template <typename... Options>
320std::vector<formats::bson::Value> Collection::Distinct(std::string field, Options&&... options) const {
321 operations::Distinct distinct_op(std::move(field));
322 (distinct_op.SetOption(std::forward<Options>(options)), ...);
323 return Execute(distinct_op);
324}
325
326template <typename... Options>
327std::vector<formats::bson::Value> Collection::Distinct(
328 std::string field,
329 formats::bson::Document filter,
330 Options&&... options
331) const {
332 operations::Distinct distinct_op(std::move(field), std::move(filter));
333 (distinct_op.SetOption(std::forward<Options>(options)), ...);
334 return Execute(distinct_op);
335}
336
337} // namespace storages::mongo
338
339USERVER_NAMESPACE_END