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 a single matching document with an aggregation pipeline
80 /// @note `update` must be either an update document or an aggregation pipeline array
81 /// @note Available starting in MongoDB 4.2
82 /// @see options::Upsert
83 template <typename... Options>
84 WriteResult UpdateOne(formats::bson::Document selector, formats::bson::Value update, Options&&... options);
85
86 /// @brief Updates all matching documents
87 /// @see options::Upsert
88 template <typename... Options>
89 WriteResult UpdateMany(formats::bson::Document selector, formats::bson::Document update, Options&&... options);
90
91 /// @brief Updates all matching documents with an aggregation pipeline
92 /// @note `update` must be either an update document or an aggregation pipeline array
93 /// @note Available starting in MongoDB 4.2
94 /// @see options::Upsert
95 template <typename... Options>
96 WriteResult UpdateMany(formats::bson::Document selector, formats::bson::Value update, Options&&... options);
97
98 /// Deletes a single matching document
99 template <typename... Options>
100 WriteResult DeleteOne(formats::bson::Document selector, Options&&... options);
101
102 /// Deletes all matching documents
103 template <typename... Options>
104 WriteResult DeleteMany(formats::bson::Document selector, Options&&... options);
105
106 /// @brief Atomically updates a single matching document
107 /// @see options::ReturnNew
108 /// @see options::Upsert
109 template <typename... Options>
111 formats::bson::Document query,
112 const formats::bson::Document& update,
113 Options&&... options
114 );
115
116 /// Atomically removes a single matching document
117 template <typename... Options>
118 WriteResult FindAndRemove(formats::bson::Document query, Options&&... options);
119
120 /// Drop collection
121 template <typename... Options>
122 void Drop(Options&&... options);
123
124 /// Efficiently executes multiple operations in order, stops on error
125 template <typename... Options>
126 operations::Bulk MakeOrderedBulk(Options&&... options);
127
128 /// Efficiently executes multiple operations out of order, continues on error
129 template <typename... Options>
130 operations::Bulk MakeUnorderedBulk(Options&&... options);
131
132 /// @brief Executes an aggregation pipeline
133 /// @param pipeline an array of aggregation operations
134 /// @param options see @ref storages::mongo::options
135 template <typename... Options>
136 Cursor Aggregate(formats::bson::Value pipeline, Options&&... options);
137
138 /// @brief Retrieves distinct values for a specified field
139 /// @param field name of the field for which to return distinct values
140 /// @param options see @ref storages::mongo::options
141 template <typename... Options>
142 std::vector<formats::bson::Value> Distinct(std::string field, Options&&... options) const;
143
144 /// @brief Retrieves distinct values for a specified field with a query filter
145 /// @param field name of the field for which to return distinct values
146 /// @param filter query that specifies the documents from which to retrieve distinct values
147 /// @param options see @ref storages::mongo::options
148 template <typename... Options>
149 std::vector<formats::bson::Value> Distinct(std::string field, formats::bson::Document filter, Options&&... options)
150 const;
151
152 /// Get collection name
153 const std::string& GetCollectionName() const;
154
155 /// @name Prepared operation executors
156 /// @{
157 size_t Execute(const operations::Count&) const;
158 size_t Execute(const operations::CountApprox&) const;
159 Cursor Execute(const operations::Find&) const;
160 std::vector<formats::bson::Value> Execute(const operations::Distinct&) const;
161 WriteResult Execute(const operations::InsertOne&);
162 WriteResult Execute(const operations::InsertMany&);
163 WriteResult Execute(const operations::ReplaceOne&);
164 WriteResult Execute(const operations::Update&);
165 WriteResult Execute(const operations::Delete&);
166 WriteResult Execute(const operations::FindAndModify&);
167 WriteResult Execute(const operations::FindAndRemove&);
168 WriteResult Execute(operations::Bulk&&);
169 Cursor Execute(const operations::Aggregate&);
170 void Execute(const operations::Drop&);
171 /// @}
172private:
173 std::shared_ptr<impl::CollectionImpl> impl_;
174 bool transactional_{false};
175};
176
177template <typename... Options>
178size_t Collection::Count(formats::bson::Document filter, Options&&... options) const {
179 operations::Count count_op(std::move(filter));
180 (count_op.SetOption(std::forward<Options>(options)), ...);
181 return Execute(count_op);
182}
183
184template <typename... Options>
185size_t Collection::CountApprox(Options&&... options) const {
186 operations::CountApprox count_approx_op;
187 (count_approx_op.SetOption(std::forward<Options>(options)), ...);
188 return Execute(count_approx_op);
189}
190
191namespace impl {
192
193template <typename Option, typename... Options>
194using HasOptionHelper = std::disjunction<std::is_same<std::decay_t<Options>, Option>...>;
195
196template <typename Option, typename... Options>
197static constexpr bool kHasOption = HasOptionHelper<Option, Options...>::value;
198
199} // namespace impl
200
201template <typename... Options>
202Cursor Collection::Find(formats::bson::Document filter, Options&&... options) const {
203 UINVARIANT(!transactional_, "Find is not supported for transaction collections");
204 operations::Find find_op(std::move(filter));
205 (find_op.SetOption(std::forward<Options>(options)), ...);
206 return Execute(find_op);
207}
208
209template <typename... Options>
210std::optional<formats::bson::Document> Collection::FindOne(formats::bson::Document filter, Options&&... options) const {
211 static_assert(
212 !(std::is_same<std::decay_t<Options>, options::Limit>::value || ...),
213 "Limit option cannot be used in FindOne"
214 );
215 operations::Find find_op(std::move(filter));
216 find_op.SetOption(options::Limit{1});
217 (find_op.SetOption(std::forward<Options>(options)), ...);
218 auto cursor = Execute(find_op);
219 if (cursor.begin() == cursor.end()) {
220 return {};
221 }
222 return *cursor.begin();
223}
224
225template <typename... Options>
226WriteResult Collection::InsertOne(formats::bson::Document document, Options&&... options) {
227 operations::InsertOne insert_op(std::move(document));
228 (insert_op.SetOption(std::forward<Options>(options)), ...);
229 return Execute(insert_op);
230}
231
232template <typename... Options>
233WriteResult Collection::InsertMany(std::vector<formats::bson::Document> documents, Options&&... options) {
234 operations::InsertMany insert_op(std::move(documents));
235 (insert_op.SetOption(std::forward<Options>(options)), ...);
236 return Execute(insert_op);
237}
238
239template <typename... Options>
241 formats::bson::Document selector,
242 formats::bson::Document replacement,
243 Options&&... options
244) {
245 operations::ReplaceOne replace_op(std::move(selector), std::move(replacement));
246 (replace_op.SetOption(std::forward<Options>(options)), ...);
247 return Execute(replace_op);
248}
249
250template <typename... Options>
252 formats::bson::Document selector,
253 formats::bson::Document update,
254 Options&&... options
255) {
256 operations::Update update_op(operations::Update::Mode::kSingle, std::move(selector), std::move(update));
257 (update_op.SetOption(std::forward<Options>(options)), ...);
258 return Execute(update_op);
259}
260
261template <typename... Options>
262WriteResult Collection::UpdateOne(formats::bson::Document selector, formats::bson::Value update, Options&&... options) {
263 operations::Update update_op(operations::Update::Mode::kSingle, std::move(selector), std::move(update));
264 (update_op.SetOption(std::forward<Options>(options)), ...);
265 return Execute(update_op);
266}
267
268template <typename... Options>
270 formats::bson::Document selector,
271 formats::bson::Document update,
272 Options&&... options
273) {
274 operations::Update update_op(operations::Update::Mode::kMulti, std::move(selector), std::move(update));
275 (update_op.SetOption(std::forward<Options>(options)), ...);
276 return Execute(update_op);
277}
278
279template <typename... Options>
281 formats::bson::Document selector,
282 formats::bson::Value update,
283 Options&&... options
284) {
285 operations::Update update_op(operations::Update::Mode::kMulti, std::move(selector), std::move(update));
286 (update_op.SetOption(std::forward<Options>(options)), ...);
287 return Execute(update_op);
288}
289
290template <typename... Options>
291WriteResult Collection::DeleteOne(formats::bson::Document selector, Options&&... options) {
292 operations::Delete delete_op(operations::Delete::Mode::kSingle, std::move(selector));
293 (delete_op.SetOption(std::forward<Options>(options)), ...);
294 return Execute(delete_op);
295}
296
297template <typename... Options>
298WriteResult Collection::DeleteMany(formats::bson::Document selector, Options&&... options) {
299 operations::Delete delete_op(operations::Delete::Mode::kMulti, std::move(selector));
300 (delete_op.SetOption(std::forward<Options>(options)), ...);
301 return Execute(delete_op);
302}
303
304template <typename... Options>
306 formats::bson::Document query,
307 const formats::bson::Document& update,
308 Options&&... options
309) {
310 operations::FindAndModify fam_op(std::move(query), update);
311 (fam_op.SetOption(std::forward<Options>(options)), ...);
312 return Execute(fam_op);
313}
314
315template <typename... Options>
316WriteResult Collection::FindAndRemove(formats::bson::Document query, Options&&... options) {
317 operations::FindAndRemove fam_op(std::move(query));
318 (fam_op.SetOption(std::forward<Options>(options)), ...);
319 return Execute(fam_op);
320}
321
322template <typename... Options>
323void Collection::Drop(Options&&... options) {
324 operations::Drop drop_op;
325 (drop_op.SetOption(std::forward<Options>(options)), ...);
326 Execute(drop_op);
327}
328
329template <typename... Options>
330operations::Bulk Collection::MakeOrderedBulk(Options&&... options) {
331 operations::Bulk bulk(operations::Bulk::Mode::kOrdered);
332 (bulk.SetOption(std::forward<Options>(options)), ...);
333 return bulk;
334}
335
336template <typename... Options>
338 operations::Bulk bulk(operations::Bulk::Mode::kUnordered);
339 (bulk.SetOption(std::forward<Options>(options)), ...);
340 return bulk;
341}
342
343template <typename... Options>
344Cursor Collection::Aggregate(formats::bson::Value pipeline, Options&&... options) {
345 UINVARIANT(!transactional_, "Aggregate is not supported for transaction collections");
346 operations::Aggregate aggregate(std::move(pipeline));
347 (aggregate.SetOption(std::forward<Options>(options)), ...);
348 return Execute(aggregate);
349}
350
351template <typename... Options>
352std::vector<formats::bson::Value> Collection::Distinct(std::string field, Options&&... options) const {
353 operations::Distinct distinct_op(std::move(field));
354 (distinct_op.SetOption(std::forward<Options>(options)), ...);
355 return Execute(distinct_op);
356}
357
358template <typename... Options>
359std::vector<formats::bson::Value> Collection::Distinct(
360 std::string field,
361 formats::bson::Document filter,
362 Options&&... options
363) const {
364 operations::Distinct distinct_op(std::move(field), std::move(filter));
365 (distinct_op.SetOption(std::forward<Options>(options)), ...);
366 return Execute(distinct_op);
367}
368
369} // namespace storages::mongo
370
371USERVER_NAMESPACE_END