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
19USERVER_NAMESPACE_BEGIN
20
21namespace storages::mongo {
22
23namespace impl {
24class CollectionImpl;
25} // namespace impl
26
27/// @brief MongoDB collection handle, the main way to operate with MongoDB.
28///
29/// Usually retrieved from storages::mongo::Pool
30///
31/// ## Example:
32///
33/// @snippet storages/mongo/collection_mongotest.hpp Sample Mongo usage
35 public:
36 /// @cond
37 // For internal use only.
38 explicit Collection(std::shared_ptr<impl::CollectionImpl>);
39 /// @endcond
40
41 /// @brief Returns the number of documents matching the query
42 /// @warning Unless explicitly overridden, runs CountApprox for empty filters
43 /// @see options::ForceCountImpl
44 template <typename... Options>
46
47 /// @brief Returns an approximated count of all documents in the collection
48 /// @note This method uses collection metadata and should be faster
49 template <typename... Options>
51
52 /// Performs a query on the collection
53 template <typename... Options>
54 Cursor Find(formats::bson::Document filter, Options&&... options) const;
55
56 /// Retrieves a single document from the collection
57 template <typename... Options>
58 std::optional<formats::bson::Document> FindOne(formats::bson::Document filter,
59 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,
68 Options&&... options);
69
70 /// @brief Replaces a single matching document
71 /// @see options::Upsert
72 template <typename... Options>
73 WriteResult ReplaceOne(formats::bson::Document selector,
74 formats::bson::Document replacement,
75 Options&&... options);
76
77 /// @brief Updates a single matching document
78 /// @see options::Upsert
79 template <typename... Options>
80 WriteResult UpdateOne(formats::bson::Document selector,
81 formats::bson::Document update, Options&&... options);
82
83 /// @brief Updates all matching documents
84 /// @see options::Upsert
85 template <typename... Options>
86 WriteResult UpdateMany(formats::bson::Document selector,
87 formats::bson::Document update, Options&&... options);
88
89 /// Deletes a single matching document
90 template <typename... Options>
91 WriteResult DeleteOne(formats::bson::Document selector, Options&&... options);
92
93 /// Deletes all matching documents
94 template <typename... Options>
95 WriteResult DeleteMany(formats::bson::Document selector,
96 Options&&... options);
97
98 /// @brief Atomically updates a single matching document
99 /// @see options::ReturnNew
100 /// @see options::Upsert
101 template <typename... Options>
102 WriteResult FindAndModify(formats::bson::Document query,
103 const formats::bson::Document& update,
104 Options&&... options);
105
106 /// Atomically removes a single matching document
107 template <typename... Options>
108 WriteResult FindAndRemove(formats::bson::Document query,
109 Options&&... options);
110
111 /// Drop collection
112 template <typename... Options>
113 void Drop(Options&&... options);
114
115 /// Efficiently executes multiple operations in order, stops on error
116 template <typename... Options>
117 operations::Bulk MakeOrderedBulk(Options&&... options);
118
119 /// Efficiently executes multiple operations out of order, continues on error
120 template <typename... Options>
121 operations::Bulk MakeUnorderedBulk(Options&&... options);
122
123 /// @brief Executes an aggregation pipeline
124 /// @param pipeline an array of aggregation operations
125 template <typename... Options>
126 Cursor Aggregate(formats::bson::Value pipeline, Options&&... options);
127
128 /// Get collection name
129 const std::string& GetCollectionName() const;
130
131 /// @name Prepared operation executors
132 /// @{
133 size_t Execute(const operations::Count&) const;
134 size_t Execute(const operations::CountApprox&) const;
135 Cursor Execute(const operations::Find&) const;
136 WriteResult Execute(const operations::InsertOne&);
137 WriteResult Execute(const operations::InsertMany&);
138 WriteResult Execute(const operations::ReplaceOne&);
139 WriteResult Execute(const operations::Update&);
140 WriteResult Execute(const operations::Delete&);
141 WriteResult Execute(const operations::FindAndModify&);
142 WriteResult Execute(const operations::FindAndRemove&);
143 WriteResult Execute(operations::Bulk&&);
144 Cursor Execute(const operations::Aggregate&);
145 void Execute(const operations::Drop&);
146 /// @}
147 private:
148 std::shared_ptr<impl::CollectionImpl> impl_;
149};
150
151template <typename... Options>
153 Options&&... options) const {
154 operations::Count count_op(std::move(filter));
155 (count_op.SetOption(std::forward<Options>(options)), ...);
156 return Execute(count_op);
157}
158
159template <typename... Options>
161 operations::CountApprox count_approx_op;
162 (count_approx_op.SetOption(std::forward<Options>(options)), ...);
163 return Execute(count_approx_op);
164}
165
166namespace impl {
167
168template <typename Option, typename... Options>
169using HasOptionHelper =
170 std::disjunction<std::is_same<std::decay_t<Options>, Option>...>;
171
172template <typename Option, typename... Options>
173static constexpr bool kHasOption = HasOptionHelper<Option, Options...>::value;
174
175} // namespace impl
176
177template <typename... Options>
179 Options&&... options) const {
180 operations::Find find_op(std::move(filter));
181 (find_op.SetOption(std::forward<Options>(options)), ...);
182 return Execute(find_op);
183}
184
185template <typename... Options>
186std::optional<formats::bson::Document> Collection::FindOne(
187 formats::bson::Document filter, Options&&... options) const {
188 static_assert(
189 !(std::is_same<std::decay_t<Options>, options::Limit>::value || ...),
190 "Limit option cannot be used in FindOne");
191 auto cursor = Find(std::move(filter), options::Limit{1},
192 std::forward<Options>(options)...);
193 if (cursor.begin() == cursor.end()) return {};
194 return *cursor.begin();
195}
196
197template <typename... Options>
199 Options&&... options) {
200 operations::InsertOne insert_op(std::move(document));
201 (insert_op.SetOption(std::forward<Options>(options)), ...);
202 return Execute(insert_op);
203}
204
205template <typename... Options>
207 std::vector<formats::bson::Document> documents, Options&&... options) {
208 operations::InsertMany insert_op(std::move(documents));
209 (insert_op.SetOption(std::forward<Options>(options)), ...);
210 return Execute(insert_op);
211}
212
213template <typename... Options>
215 formats::bson::Document replacement,
216 Options&&... options) {
217 operations::ReplaceOne replace_op(std::move(selector),
218 std::move(replacement));
219 (replace_op.SetOption(std::forward<Options>(options)), ...);
220 return Execute(replace_op);
221}
222
223template <typename... Options>
225 formats::bson::Document update,
226 Options&&... options) {
227 operations::Update update_op(operations::Update::Mode::kSingle,
228 std::move(selector), std::move(update));
229 (update_op.SetOption(std::forward<Options>(options)), ...);
230 return Execute(update_op);
231}
232
233template <typename... Options>
235 formats::bson::Document update,
236 Options&&... options) {
237 operations::Update update_op(operations::Update::Mode::kMulti,
238 std::move(selector), std::move(update));
239 (update_op.SetOption(std::forward<Options>(options)), ...);
240 return Execute(update_op);
241}
242
243template <typename... Options>
245 Options&&... options) {
246 operations::Delete delete_op(operations::Delete::Mode::kSingle,
247 std::move(selector));
248 (delete_op.SetOption(std::forward<Options>(options)), ...);
249 return Execute(delete_op);
250}
251
252template <typename... Options>
254 Options&&... options) {
255 operations::Delete delete_op(operations::Delete::Mode::kMulti,
256 std::move(selector));
257 (delete_op.SetOption(std::forward<Options>(options)), ...);
258 return Execute(delete_op);
259}
260
261template <typename... Options>
263 const formats::bson::Document& update,
264 Options&&... options) {
265 operations::FindAndModify fam_op(std::move(query), update);
266 (fam_op.SetOption(std::forward<Options>(options)), ...);
267 return Execute(fam_op);
268}
269
270template <typename... Options>
272 Options&&... options) {
273 operations::FindAndRemove fam_op(std::move(query));
274 (fam_op.SetOption(std::forward<Options>(options)), ...);
275 return Execute(fam_op);
276}
277
278template <typename... Options>
279void Collection::Drop(Options&&... options) {
280 operations::Drop drop_op;
281 (drop_op.SetOption(std::forward<Options>(options)), ...);
282 return Execute(drop_op);
283}
284
285template <typename... Options>
286operations::Bulk Collection::MakeOrderedBulk(Options&&... options) {
287 operations::Bulk bulk(operations::Bulk::Mode::kOrdered);
288 (bulk.SetOption(std::forward<Options>(options)), ...);
289 return bulk;
290}
291
292template <typename... Options>
294 operations::Bulk bulk(operations::Bulk::Mode::kUnordered);
295 (bulk.SetOption(std::forward<Options>(options)), ...);
296 return bulk;
297}
298
299template <typename... Options>
301 Options&&... options) {
302 operations::Aggregate aggregate(std::move(pipeline));
303 (aggregate.SetOption(std::forward<Options>(options)), ...);
304 return Execute(aggregate);
305}
306
307} // namespace storages::mongo
308
309USERVER_NAMESPACE_END