userver: userver/storages/mongo/collection.hpp Source File
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages Concepts
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
35public:
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>
45 size_t Count(formats::bson::Document filter, Options&&... options) const;
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>
50 size_t CountApprox(Options&&... options) const;
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, Options&&... options) const;
59
60 /// Inserts a single document into the collection
61 template <typename... Options>
62 WriteResult InsertOne(formats::bson::Document document, Options&&... options);
63
64 /// Inserts multiple documents into the collection
65 template <typename... Options>
66 WriteResult InsertMany(std::vector<formats::bson::Document> documents, Options&&... options);
67
68 /// @brief Replaces a single matching document
69 /// @see options::Upsert
70 template <typename... Options>
71 WriteResult ReplaceOne(formats::bson::Document selector, formats::bson::Document replacement, Options&&... options);
72
73 /// @brief Updates a single matching document
74 /// @see options::Upsert
75 template <typename... Options>
76 WriteResult UpdateOne(formats::bson::Document selector, formats::bson::Document update, Options&&... options);
77
78 /// @brief Updates all matching documents
79 /// @see options::Upsert
80 template <typename... Options>
81 WriteResult UpdateMany(formats::bson::Document selector, formats::bson::Document update, Options&&... options);
82
83 /// Deletes a single matching document
84 template <typename... Options>
85 WriteResult DeleteOne(formats::bson::Document selector, Options&&... options);
86
87 /// Deletes all matching documents
88 template <typename... Options>
89 WriteResult DeleteMany(formats::bson::Document selector, Options&&... options);
90
91 /// @brief Atomically updates a single matching document
92 /// @see options::ReturnNew
93 /// @see options::Upsert
94 template <typename... Options>
96 FindAndModify(formats::bson::Document query, const formats::bson::Document& update, Options&&... options);
97
98 /// Atomically removes a single matching document
99 template <typename... Options>
100 WriteResult FindAndRemove(formats::bson::Document query, Options&&... options);
101
102 /// Drop collection
103 template <typename... Options>
104 void Drop(Options&&... options);
105
106 /// Efficiently executes multiple operations in order, stops on error
107 template <typename... Options>
108 operations::Bulk MakeOrderedBulk(Options&&... options);
109
110 /// Efficiently executes multiple operations out of order, continues on error
111 template <typename... Options>
112 operations::Bulk MakeUnorderedBulk(Options&&... options);
113
114 /// @brief Executes an aggregation pipeline
115 /// @param pipeline an array of aggregation operations
116 /// @param options see @ref storages::mongo::options
117 template <typename... Options>
118 Cursor Aggregate(formats::bson::Value pipeline, Options&&... options);
119
120 /// Get collection name
121 const std::string& GetCollectionName() const;
122
123 /// @name Prepared operation executors
124 /// @{
125 size_t Execute(const operations::Count&) const;
126 size_t Execute(const operations::CountApprox&) const;
127 Cursor Execute(const operations::Find&) const;
128 WriteResult Execute(const operations::InsertOne&);
129 WriteResult Execute(const operations::InsertMany&);
130 WriteResult Execute(const operations::ReplaceOne&);
131 WriteResult Execute(const operations::Update&);
132 WriteResult Execute(const operations::Delete&);
133 WriteResult Execute(const operations::FindAndModify&);
134 WriteResult Execute(const operations::FindAndRemove&);
135 WriteResult Execute(operations::Bulk&&);
136 Cursor Execute(const operations::Aggregate&);
137 void Execute(const operations::Drop&);
138 /// @}
139private:
140 std::shared_ptr<impl::CollectionImpl> impl_;
141};
142
143template <typename... Options>
144size_t Collection::Count(formats::bson::Document filter, Options&&... options) const {
145 operations::Count count_op(std::move(filter));
146 (count_op.SetOption(std::forward<Options>(options)), ...);
147 return Execute(count_op);
148}
149
150template <typename... Options>
151size_t Collection::CountApprox(Options&&... options) const {
152 operations::CountApprox count_approx_op;
153 (count_approx_op.SetOption(std::forward<Options>(options)), ...);
154 return Execute(count_approx_op);
155}
156
157namespace impl {
158
159template <typename Option, typename... Options>
160using HasOptionHelper = std::disjunction<std::is_same<std::decay_t<Options>, Option>...>;
161
162template <typename Option, typename... Options>
163static constexpr bool kHasOption = HasOptionHelper<Option, Options...>::value;
164
165} // namespace impl
166
167template <typename... Options>
168Cursor Collection::Find(formats::bson::Document filter, Options&&... options) const {
169 operations::Find find_op(std::move(filter));
170 (find_op.SetOption(std::forward<Options>(options)), ...);
171 return Execute(find_op);
172}
173
174template <typename... Options>
175std::optional<formats::bson::Document> Collection::FindOne(formats::bson::Document filter, Options&&... options) const {
176 static_assert(
177 !(std::is_same<std::decay_t<Options>, options::Limit>::value || ...), "Limit option cannot be used in FindOne"
178 );
179 auto cursor = Find(std::move(filter), options::Limit{1}, std::forward<Options>(options)...);
180 if (cursor.begin() == cursor.end()) return {};
181 return *cursor.begin();
182}
183
184template <typename... Options>
185WriteResult Collection::InsertOne(formats::bson::Document document, Options&&... options) {
186 operations::InsertOne insert_op(std::move(document));
187 (insert_op.SetOption(std::forward<Options>(options)), ...);
188 return Execute(insert_op);
189}
190
191template <typename... Options>
192WriteResult Collection::InsertMany(std::vector<formats::bson::Document> documents, Options&&... options) {
193 operations::InsertMany insert_op(std::move(documents));
194 (insert_op.SetOption(std::forward<Options>(options)), ...);
195 return Execute(insert_op);
196}
197
198template <typename... Options>
200Collection::ReplaceOne(formats::bson::Document selector, formats::bson::Document replacement, Options&&... options) {
201 operations::ReplaceOne replace_op(std::move(selector), std::move(replacement));
202 (replace_op.SetOption(std::forward<Options>(options)), ...);
203 return Execute(replace_op);
204}
205
206template <typename... Options>
208Collection::UpdateOne(formats::bson::Document selector, formats::bson::Document update, Options&&... options) {
209 operations::Update update_op(operations::Update::Mode::kSingle, std::move(selector), std::move(update));
210 (update_op.SetOption(std::forward<Options>(options)), ...);
211 return Execute(update_op);
212}
213
214template <typename... Options>
216Collection::UpdateMany(formats::bson::Document selector, formats::bson::Document update, Options&&... options) {
217 operations::Update update_op(operations::Update::Mode::kMulti, std::move(selector), std::move(update));
218 (update_op.SetOption(std::forward<Options>(options)), ...);
219 return Execute(update_op);
220}
221
222template <typename... Options>
223WriteResult Collection::DeleteOne(formats::bson::Document selector, Options&&... options) {
224 operations::Delete delete_op(operations::Delete::Mode::kSingle, std::move(selector));
225 (delete_op.SetOption(std::forward<Options>(options)), ...);
226 return Execute(delete_op);
227}
228
229template <typename... Options>
230WriteResult Collection::DeleteMany(formats::bson::Document selector, Options&&... options) {
231 operations::Delete delete_op(operations::Delete::Mode::kMulti, std::move(selector));
232 (delete_op.SetOption(std::forward<Options>(options)), ...);
233 return Execute(delete_op);
234}
235
236template <typename... Options>
238Collection::FindAndModify(formats::bson::Document query, const formats::bson::Document& update, Options&&... options) {
239 operations::FindAndModify fam_op(std::move(query), update);
240 (fam_op.SetOption(std::forward<Options>(options)), ...);
241 return Execute(fam_op);
242}
243
244template <typename... Options>
245WriteResult Collection::FindAndRemove(formats::bson::Document query, Options&&... options) {
246 operations::FindAndRemove fam_op(std::move(query));
247 (fam_op.SetOption(std::forward<Options>(options)), ...);
248 return Execute(fam_op);
249}
250
251template <typename... Options>
252void Collection::Drop(Options&&... options) {
253 operations::Drop drop_op;
254 (drop_op.SetOption(std::forward<Options>(options)), ...);
255 return Execute(drop_op);
256}
257
258template <typename... Options>
259operations::Bulk Collection::MakeOrderedBulk(Options&&... options) {
260 operations::Bulk bulk(operations::Bulk::Mode::kOrdered);
261 (bulk.SetOption(std::forward<Options>(options)), ...);
262 return bulk;
263}
264
265template <typename... Options>
267 operations::Bulk bulk(operations::Bulk::Mode::kUnordered);
268 (bulk.SetOption(std::forward<Options>(options)), ...);
269 return bulk;
270}
271
272template <typename... Options>
273Cursor Collection::Aggregate(formats::bson::Value pipeline, Options&&... options) {
274 operations::Aggregate aggregate(std::move(pipeline));
275 (aggregate.SetOption(std::forward<Options>(options)), ...);
276 return Execute(aggregate);
277}
278
279} // namespace storages::mongo
280
281USERVER_NAMESPACE_END