Skip to content
This repository was archived by the owner on Nov 10, 2025. It is now read-only.

Commit e592a81

Browse files
committed
CXXODM-47 Mirror collection semantics in model where appropriate
1 parent fe9d4c2 commit e592a81

File tree

5 files changed

+449
-161
lines changed

5 files changed

+449
-161
lines changed

src/mongo_odm/model.hpp

Lines changed: 223 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -19,22 +19,12 @@
1919
#include <bsoncxx/oid.hpp>
2020
#include <mongo_odm/config/prelude.hpp>
2121
#include <mongo_odm/odm_collection.hpp>
22+
#include <mongo_odm/util.hpp>
2223
#include <mongocxx/collection.hpp>
2324

2425
namespace mongo_odm {
2526
MONGO_ODM_INLINE_NAMESPACE_BEGIN
2627

27-
/**
28-
* Helper type trait widget that helps properly forward arguments to _id constructor.
29-
* FirstTypeIsTheSame<T1, T2, ...>::value will be true when T1 and T2 are of the same type, and
30-
* false otherwise.
31-
*/
32-
template <typename... Ts>
33-
struct FirstTypeIsTheSame : public std::false_type {};
34-
35-
template <typename T, typename T2, typename... Ts>
36-
struct FirstTypeIsTheSame<T, T2, Ts...> : public std::is_same<T, std::decay_t<T2>> {};
37-
3828
template <typename T, typename IdType = bsoncxx::oid>
3929
class model {
4030
private:
@@ -56,12 +46,34 @@ class model {
5646
* @param ts
5747
* The variadic pack of arguments to be forwarded to the constructor of IdType.
5848
*/
59-
template <typename... Ts, typename = std::enable_if_t<!FirstTypeIsTheSame<model, Ts...>::value>>
49+
template <typename... Ts,
50+
typename = std::enable_if_t<!first_two_types_are_same<model, Ts...>::value>>
6051
model(Ts&&... ts) : _id(std::forward<Ts>(ts)...) {
6152
}
6253

6354
model() = default;
6455

56+
/**
57+
* Counts the number of documents matching the provided filter.
58+
*
59+
* @param filter
60+
* The filter that documents must match in order to be counted.
61+
* If a filter is not provided, count() will count the number
62+
* of documents in the entire collection.
63+
* @param options
64+
* Optional arguments, see mongocxx::options::count.
65+
*
66+
* @return The count of the documents that matched the filter.
67+
* @throws mongocxx::exception::query if the count operation fails.
68+
*
69+
* @see https://docs.mongodb.com/manual/reference/command/count/
70+
*/
71+
static std::int64_t count(
72+
bsoncxx::document::view_or_value filter = bsoncxx::document::view_or_value{},
73+
const mongocxx::options::count& options = mongocxx::options::count()) {
74+
return _coll.collection().count(filter, options);
75+
}
76+
6577
/**
6678
* Returns a copy of the underlying collection.
6779
*
@@ -72,6 +84,44 @@ class model {
7284
return _coll.collection();
7385
}
7486

87+
/**
88+
* Deletes all matching documents from the collection.
89+
*
90+
* @param filter
91+
* Document view representing the data to be deleted.
92+
* @param options
93+
* Optional arguments, see mongocxx::options::delete_options.
94+
*
95+
* @return The optional result of performing the deletion, a mongocxx::result::delete_result.
96+
* @throws mongocxx::exception::write if the delete fails.
97+
*
98+
* @see http://docs.mongodb.com/manual/reference/command/delete/
99+
*/
100+
static mongocxx::stdx::optional<mongocxx::result::delete_result> delete_many(
101+
bsoncxx::document::view_or_value filter,
102+
const mongocxx::options::delete_options& options = mongocxx::options::delete_options()) {
103+
return _coll.collection().delete_many(filter, options);
104+
}
105+
106+
/**
107+
* Deletes a single matching document from the collection.
108+
*
109+
* @param filter
110+
* Document view representing the data to be deleted.
111+
* @param options
112+
* Optional arguments, see mongocxx::options::delete_options.
113+
*
114+
* @return The optional result of performing the deletion, a mongocxx::result::delete_result.
115+
* @throws mongocxx::exception::write if the delete fails.
116+
*
117+
* @see http://docs.mongodb.com/manual/reference/command/delete/
118+
*/
119+
static mongocxx::stdx::optional<mongocxx::result::delete_result> delete_one(
120+
bsoncxx::document::view_or_value filter,
121+
const mongocxx::options::delete_options& options = mongocxx::options::delete_options()) {
122+
return _coll.collection().delete_one(filter, options);
123+
}
124+
75125
/**
76126
* Drops the underlying collection and all its contained documents from the database.
77127
*
@@ -83,6 +133,139 @@ class model {
83133
_coll.collection().drop();
84134
}
85135

136+
/**
137+
* Finds the documents in this collection which match the provided filter.
138+
*
139+
* @param filter
140+
* Document view representing a document that should match the query.
141+
* @param options
142+
* Optional arguments, see mongocxx::options::find
143+
*
144+
* @return Cursor with deserialized objects from the collection.
145+
* @throws
146+
* If the find failed, the returned cursor will throw mongocxx::exception::query when it
147+
* is iterated.
148+
*
149+
* @see https://docs.mongodb.com/manual/tutorial/query-documents/
150+
*/
151+
static deserializing_cursor<T> find(
152+
bsoncxx::document::view_or_value filter,
153+
const mongocxx::options::find& options = mongocxx::options::find()) {
154+
return _coll.find(std::move(filter), options);
155+
}
156+
157+
/**
158+
* Finds a single document in this collection that matches the provided filter.
159+
*
160+
* @param filter
161+
* Document view representing a document that should match the query.
162+
* @param options
163+
* Optional arguments, see mongocxx::options::find
164+
*
165+
* @return An optional object that matched the filter.
166+
* @throws mongocxx::exception::query if the operation fails.
167+
*
168+
* @see https://docs.mongodb.com/manual/tutorial/query-documents/
169+
*/
170+
static mongocxx::stdx::optional<T> find_one(
171+
bsoncxx::document::view_or_value filter,
172+
const mongocxx::options::find& options = mongocxx::options::find()) {
173+
return _coll.find_one(std::move(filter), options);
174+
}
175+
176+
/**
177+
* Inserts multiple object of the model into the collection.
178+
*
179+
* @warning This method uses the bulk insert command to execute the insertion as opposed to
180+
* the legacy OP_INSERT wire protocol message. As a result, using this method to insert
181+
* many documents on MongoDB < 2.6 will be slow.
182+
*
183+
* @tparam containter_type
184+
* The container type. Must contain an iterator that yields objects of this model.
185+
*
186+
* @param container
187+
* Container of model objects to insert.
188+
* @param options
189+
* Optional arguments, see mongocxx::options::insert.
190+
*
191+
* @see https://docs.mongodb.com/manual/tutorial/insert-documents/
192+
*
193+
* @return The result of attempting to performing the insert.
194+
* @throws mongocxx::exception::write when the operation fails.
195+
*/
196+
template <typename container_type,
197+
typename = std::enable_if_t<container_of_v<container_type, T>>>
198+
static mongocxx::stdx::optional<mongocxx::result::insert_many> insert_many(
199+
const container_type& container,
200+
const mongocxx::options::insert& options = mongocxx::options::insert()) {
201+
return insert_many(container.begin(), container.end(), options);
202+
}
203+
204+
/**
205+
* Inserts multiple objects of the model into the collection.
206+
*
207+
* @warning This method uses the bulk insert command to execute the insertion as opposed to
208+
* the legacy OP_INSERT wire protocol message. As a result, using this method to insert
209+
* many documents on MongoDB < 2.6 will be slow.
210+
*
211+
* @tparam object_iterator_type
212+
* The iterator type. Must meet the requirements for the input iterator concept with the
213+
* model class as the value type.
214+
*
215+
* @param begin
216+
* Iterator pointing to the first document to be inserted.
217+
* @param end
218+
* Iterator pointing to the end of the documents to be inserted.
219+
* @param options
220+
* Optional arguments, see mongocxx::options::insert.
221+
*
222+
* @see https://docs.mongodb.com/manual/tutorial/insert-documents/
223+
*
224+
* @return The result of attempting to performing the insert.
225+
* @throws mongocxx::exception::write if the operation fails.
226+
*
227+
*/
228+
template <typename object_iterator_type,
229+
typename = std::enable_if_t<iterator_of_v<object_iterator_type, T>>>
230+
static mongocxx::stdx::optional<mongocxx::result::insert_many> insert_many(
231+
object_iterator_type begin, object_iterator_type end,
232+
const mongocxx::options::insert& options = mongocxx::options::insert()) {
233+
return _coll.insert_many(begin, end, options);
234+
}
235+
236+
/**
237+
* Inserts a single object of the model into the collection.
238+
*
239+
* @param obj
240+
* The object of the model to insert.
241+
* @param options
242+
* Optional arguments, see mongocxx::options::insert.
243+
*
244+
* @see https://docs.mongodb.com/manual/tutorial/insert-documents/
245+
*
246+
* @return The result of attempting to perform the insert.
247+
* @throws mongocxx::exception::write if the operation fails.
248+
*/
249+
static mongocxx::stdx::optional<mongocxx::result::insert_one> insert_one(
250+
T obj, const mongocxx::options::insert& options = mongocxx::options::insert()) {
251+
return _coll.insert_one(obj, options);
252+
}
253+
254+
/**
255+
* Deletes this object from the underlying collection.
256+
*
257+
* In the terms of the CRUD specification, this uses deleteOne with the _id as the sole
258+
* argument to the query filter.
259+
*
260+
* @see https://docs.mongodb.com/manual/reference/method/db.collection.deleteOne/
261+
*/
262+
void remove() {
263+
auto id_match_filter = bsoncxx::builder::stream::document{}
264+
<< "_id" << this->_id << bsoncxx::builder::stream::finalize;
265+
266+
_coll.collection().delete_one(id_match_filter.view());
267+
}
268+
86269
/**
87270
* Sets the underlying mongocxx::collection used to store and load instances of T.
88271
*
@@ -129,58 +312,45 @@ class model {
129312
};
130313

131314
/**
132-
* Deletes this object from the underlying collection.
315+
* Updates multiple documents matching the provided filter in this collection.
133316
*
134-
* In the terms of the CRUD specification, this uses deleteOne with the _id as the sole
135-
* argument to the query filter.
317+
* @param filter
318+
* Document representing the match criteria.
319+
* @param update
320+
* Document representing the update to be applied to matching documents.
321+
* @param options
322+
* Optional arguments, see mongocxx::options::update.
136323
*
137-
* @see https://docs.mongodb.com/manual/reference/method/db.collection.deleteOne/
138-
*/
139-
void remove() {
140-
auto id_match_filter = bsoncxx::builder::stream::document{}
141-
<< "_id" << this->_id << bsoncxx::builder::stream::finalize;
142-
143-
_coll.collection().delete_one(id_match_filter.view());
144-
}
145-
146-
/**
147-
* Finds the documents in this collection which match the provided filter.
148-
*
149-
* @param filter
150-
* Document view representing a document that should match the query.
151-
* @param options
152-
* Optional arguments, see mongocxx::options::find
153-
*
154-
* @return Cursor with deserialized objects from the collection.
155-
* @throws
156-
* If the find failed, the returned cursor will throw mongocxx::exception::query when it
157-
* is iterated.
324+
* @return The result of attempting to update multiple documents.
325+
* @throws exception::write if the update operation fails.
158326
*
159-
* @see https://docs.mongodb.com/manual/tutorial/query-documents/
327+
* @see http://docs.mongodb.com/manual/reference/command/update/
160328
*/
161-
static deserializing_cursor<T> find(
162-
bsoncxx::document::view_or_value filter,
163-
const mongocxx::options::find& options = mongocxx::options::find()) {
164-
return _coll.find(std::move(filter), options);
329+
static mongocxx::stdx::optional<mongocxx::result::update> update_many(
330+
bsoncxx::document::view_or_value filter, bsoncxx::document::view_or_value update,
331+
const mongocxx::options::update& options = mongocxx::options::update()) {
332+
return _coll.collection().update_many(filter, update, options);
165333
}
166334

167335
/**
168-
* Finds a single document in this collection that matches the provided filter.
336+
* Updates a single document matching the provided filter in this collection.
169337
*
170-
* @param filter
171-
* Document view representing a document that should match the query.
172-
* @param options
173-
* Optional arguments, see mongocxx::options::find
338+
* @param filter
339+
* Document representing the match criteria.
340+
* @param update
341+
* Document representing the update to be applied to a matching document.
342+
* @param options
343+
* Optional arguments, see mongocxx::options::update.
174344
*
175-
* @return An optional object that matched the filter.
176-
* @throws mongocxx::exception::query if the operation fails.
345+
* @return The result of attempting to update a document.
346+
* @throws mongocxx::exception::write if the update operation fails.
177347
*
178-
* @see https://docs.mongodb.com/manual/tutorial/query-documents/
348+
* @see http://docs.mongodb.com/manual/reference/command/update/
179349
*/
180-
static mongocxx::stdx::optional<T> find_one(
181-
bsoncxx::document::view_or_value filter,
182-
const mongocxx::options::find& options = mongocxx::options::find()) {
183-
return _coll.find_one(std::move(filter), options);
350+
static mongocxx::stdx::optional<mongocxx::result::update> update_one(
351+
bsoncxx::document::view_or_value filter, bsoncxx::document::view_or_value update,
352+
const mongocxx::options::update& options = mongocxx::options::update()) {
353+
return _coll.collection().update_many(filter, update, options);
184354
}
185355

186356
protected:

0 commit comments

Comments
 (0)