Skip to content

Commit 0f10af9

Browse files
committed
CXX-1359 Replace use of index options in API with BSON document
This commit also adds a cast operator to mongocxx::options::index so existing code will still work.
1 parent e80123f commit 0f10af9

File tree

6 files changed

+207
-136
lines changed

6 files changed

+207
-136
lines changed

src/mongocxx/collection.cpp

Lines changed: 23 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@
6565
#include <mongocxx/config/private/prelude.hh>
6666

6767
using bsoncxx::builder::basic::kvp;
68+
using bsoncxx::builder::basic::make_array;
6869
using bsoncxx::builder::basic::make_document;
6970
using bsoncxx::builder::basic::sub_array;
7071
using bsoncxx::builder::basic::sub_document;
@@ -752,136 +753,43 @@ std::int64_t collection::count(view_or_value filter, const options::count& optio
752753
return result;
753754
}
754755

755-
bsoncxx::document::value collection::create_index(view_or_value keys,
756-
const options::index& options) {
757-
scoped_bson_t bson_keys{keys};
758-
bson_error_t error;
759-
::mongoc_index_opt_geo_t geo_opt{};
760-
::mongoc_index_opt_t opt{};
761-
::mongoc_index_opt_wt_t wt_opt{};
762-
libmongoc::index_opt_init(&opt);
763-
764-
// keep our safe copies alive
765-
bsoncxx::string::view_or_value name_copy{};
766-
bsoncxx::string::view_or_value wt_config_copy{};
767-
bsoncxx::string::view_or_value default_language_copy{};
768-
bsoncxx::string::view_or_value language_override_copy{};
769-
770-
if (options.background()) {
771-
opt.background = *options.background();
772-
}
773-
774-
if (options.unique()) {
775-
opt.unique = *options.unique();
776-
}
777-
778-
if (options.name()) {
779-
name_copy = options.name()->terminated();
780-
opt.name = name_copy.data();
781-
}
782-
783-
if (options.sparse()) {
784-
opt.sparse = *options.sparse();
785-
}
786-
787-
if (options.storage_options()) {
788-
const options::index::wiredtiger_storage_options* wt_options;
789-
libmongoc::index_opt_wt_init(&wt_opt);
756+
bsoncxx::document::value collection::create_index(bsoncxx::document::view_or_value keys,
757+
bsoncxx::document::view_or_value opts) {
758+
using namespace bsoncxx;
790759

791-
if (options.storage_options()->type() ==
792-
::mongoc_index_storage_opt_type_t::MONGOC_INDEX_STORAGE_OPT_WIREDTIGER) {
793-
wt_options = static_cast<const options::index::wiredtiger_storage_options*>(
794-
options.storage_options().get());
760+
builder::basic::document index;
761+
document::view opts_view = opts.view();
795762

796-
if (wt_options->config_string()) {
797-
wt_config_copy = wt_options->config_string()->terminated();
798-
wt_opt.config_str = wt_config_copy.data();
799-
}
800-
opt.storage_options = reinterpret_cast<mongoc_index_opt_storage_t*>(&wt_opt);
801-
}
802-
}
763+
if (!opts_view["name"]) {
764+
scoped_bson_t keys_bson{keys};
803765

804-
if (options.expire_after()) {
805-
const auto count = options.expire_after()->count();
806-
if ((count < 0) || (count > std::numeric_limits<int32_t>::max())) {
807-
throw logic_error{error_code::k_invalid_parameter};
808-
}
809-
opt.expire_after_seconds = static_cast<std::int32_t>(count);
810-
}
766+
const auto name_from_keys = libmongoc::collection_keys_to_index_string(keys_bson.bson());
767+
const auto cleanup_name_from_keys = make_guard([&] { bson_free(name_from_keys); });
811768

812-
if (options.version()) {
813-
opt.v = *options.version();
769+
index.append(kvp("name", name_from_keys));
814770
}
815771

816-
if (options.weights()) {
817-
scoped_bson_t weights{*options.weights()};
818-
opt.weights = weights.bson();
819-
}
772+
index.append(builder::basic::concatenate(make_document(kvp("key", keys))),
773+
builder::basic::concatenate(opts));
820774

821-
if (options.default_language()) {
822-
default_language_copy = options.default_language()->terminated();
823-
opt.default_language = default_language_copy.data();
824-
}
775+
array::view_or_value index_array = make_array(index.view());
776+
document::view_or_value command =
777+
make_document(kvp("createIndexes", name()), kvp("indexes", index_array.view()));
825778

826-
if (options.language_override()) {
827-
language_override_copy = options.language_override()->terminated();
828-
opt.language_override = language_override_copy.data();
829-
}
830-
831-
if (options.collation()) {
832-
scoped_bson_t collation{*options.collation()};
833-
opt.collation = collation.bson();
834-
}
835-
836-
if (options.partial_filter_expression()) {
837-
scoped_bson_t partial_filter_expression{*options.partial_filter_expression()};
838-
opt.partial_filter_expression = partial_filter_expression.bson();
839-
}
840-
841-
if (options.twod_sphere_version() || options.twod_bits_precision() ||
842-
options.twod_location_min() || options.twod_location_max() ||
843-
options.haystack_bucket_size()) {
844-
libmongoc::index_opt_geo_init(&geo_opt);
845-
846-
if (options.twod_sphere_version()) {
847-
geo_opt.twod_sphere_version = *options.twod_sphere_version();
848-
}
849-
850-
if (options.twod_bits_precision()) {
851-
geo_opt.twod_bits_precision = *options.twod_bits_precision();
852-
}
853-
854-
if (options.twod_location_min()) {
855-
geo_opt.twod_location_min = *options.twod_location_min();
856-
}
857-
858-
if (options.twod_location_max()) {
859-
geo_opt.twod_location_max = *options.twod_location_max();
860-
}
861-
862-
if (options.haystack_bucket_size()) {
863-
geo_opt.haystack_bucket_size = *options.haystack_bucket_size();
864-
}
779+
scoped_bson_t reply;
780+
bson_error_t error;
865781

866-
opt.geo_options = &geo_opt;
867-
}
782+
scoped_bson_t command_bson{command};
783+
scoped_bson_t opts_bson{make_document()};
868784

869-
auto result = libmongoc::collection_create_index(
870-
_get_impl().collection_t, bson_keys.bson(), &opt, &error);
785+
auto result = libmongoc::collection_command_simple(
786+
_get_impl().collection_t, command_bson.bson(), NULL, reply.bson_for_init(), &error);
871787

872788
if (!result) {
873789
throw_exception<operation_exception>(error);
874790
}
875791

876-
if (options.name()) {
877-
return make_document(kvp("name", *options.name()));
878-
} else {
879-
const auto keys = libmongoc::collection_keys_to_index_string(bson_keys.bson());
880-
881-
const auto clean_keys = make_guard([&] { bson_free(keys); });
882-
883-
return make_document(kvp("name", keys));
884-
}
792+
return make_document(kvp("name", index.view()["name"].get_utf8().value));
885793
}
886794

887795
cursor collection::distinct(bsoncxx::string::view_or_value field_name,

src/mongocxx/collection.hpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -247,9 +247,8 @@ class MONGOCXX_API collection {
247247
/// @param keys
248248
/// The keys for the index: @c {a: 1, b: -1}
249249
/// @param options
250-
/// Optional arguments, see mongocxx::options::index.
250+
/// A document containing optional arguments.
251251
///
252-
/// @throws mongocxx::logic_error if the options are invalid.
253252
/// @throws mongocxx::operation_exception if index creation fails.
254253
///
255254
/// @see https://docs.mongodb.com/master/reference/command/createIndexes/
@@ -260,7 +259,7 @@ class MONGOCXX_API collection {
260259
/// 3.4+)
261260
///
262261
bsoncxx::document::value create_index(bsoncxx::document::view_or_value keys,
263-
const options::index& options = options::index());
262+
bsoncxx::document::view_or_value opts = {});
264263

265264
///
266265
/// Deletes all matching documents from the collection.

src/mongocxx/options/index.cpp

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,10 @@
1717
#include <bsoncxx/stdx/make_unique.hpp>
1818
#include <mongocxx/private/libmongoc.hh>
1919

20+
#include <bsoncxx/builder/basic/document.hpp>
2021
#include <mongocxx/config/private/prelude.hh>
22+
#include <mongocxx/exception/error_code.hpp>
23+
#include <mongocxx/exception/logic_error.hpp>
2124

2225
namespace mongocxx {
2326
MONGOCXX_INLINE_NAMESPACE_BEGIN
@@ -184,6 +187,100 @@ const stdx::optional<double>& index::haystack_bucket_size() const {
184187
return _haystack_bucket_size;
185188
}
186189

190+
index::operator bsoncxx::document::view_or_value() {
191+
using namespace bsoncxx;
192+
using builder::basic::kvp;
193+
using builder::basic::make_document;
194+
195+
builder::basic::document root;
196+
197+
if (_name) {
198+
root.append(kvp("name", *_name));
199+
}
200+
201+
if (_background) {
202+
root.append(kvp("background", *_background));
203+
}
204+
205+
if (_unique) {
206+
root.append(kvp("unique", *_unique));
207+
}
208+
209+
if (_partial_filter_expression) {
210+
root.append(kvp("partialFilterExpression", *_partial_filter_expression));
211+
}
212+
213+
if (_sparse) {
214+
root.append(kvp("sparse", *_sparse));
215+
}
216+
217+
if (_expire_after) {
218+
const auto count = _expire_after->count();
219+
if ((count < 0) || (count > std::numeric_limits<std::int32_t>::max())) {
220+
throw logic_error{error_code::k_invalid_parameter};
221+
}
222+
223+
root.append(kvp("expireAfterSeconds", types::b_int32{static_cast<std::int32_t>(count)}));
224+
}
225+
226+
if (_weights) {
227+
root.append(kvp("weights", *_weights));
228+
}
229+
230+
if (_default_language) {
231+
root.append(kvp("default_language", types::b_utf8{*_default_language}));
232+
}
233+
234+
if (_language_override) {
235+
root.append(kvp("language_override", types::b_utf8{*_language_override}));
236+
}
237+
238+
if (_twod_sphere_version) {
239+
root.append(kvp("2dsphereIndexVersion", types::b_int32{*_twod_sphere_version}));
240+
}
241+
242+
if (_twod_bits_precision) {
243+
root.append(kvp("bits", types::b_int32{*_twod_bits_precision}));
244+
}
245+
246+
if (_twod_location_min) {
247+
root.append(kvp("min", types::b_double{*_twod_location_min}));
248+
}
249+
250+
if (_twod_location_max) {
251+
root.append(kvp("max", types::b_double{*_twod_location_max}));
252+
}
253+
254+
if (_haystack_bucket_size) {
255+
root.append(kvp("bucketSize", types::b_double{*_haystack_bucket_size}));
256+
}
257+
258+
if (_collation) {
259+
root.append(kvp("collation", *_collation));
260+
}
261+
262+
if (_storage_options) {
263+
if (_storage_options->type() == MONGOC_INDEX_STORAGE_OPT_WIREDTIGER) {
264+
const options::index::wiredtiger_storage_options* wt_options =
265+
static_cast<const options::index::wiredtiger_storage_options*>(
266+
_storage_options.get());
267+
268+
bsoncxx::document::view_or_value storage_doc;
269+
if (wt_options->config_string()) {
270+
storage_doc = make_document(
271+
kvp("wiredTiger",
272+
make_document(kvp("configString", *wt_options->config_string()))));
273+
} else {
274+
storage_doc = make_document(
275+
kvp("wiredTiger", make_document(kvp("configString", types::b_null{}))));
276+
}
277+
278+
root.append(kvp("storageEngine", storage_doc));
279+
}
280+
}
281+
return root.extract();
282+
}
283+
187284
index::base_storage_options::~base_storage_options() = default;
188285

189286
index::wiredtiger_storage_options::~wiredtiger_storage_options() = default;

src/mongocxx/options/index.hpp

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
#include <bsoncxx/string/view_or_value.hpp>
2323
#include <mongocxx/stdx.hpp>
2424

25+
#include <bsoncxx/document/value.hpp>
26+
#include <bsoncxx/document/view_or_value.hpp>
2527
#include <mongocxx/config/prelude.hpp>
2628

2729
namespace mongocxx {
@@ -46,7 +48,7 @@ class MONGOCXX_API index {
4648
virtual ~base_storage_options();
4749

4850
private:
49-
friend collection;
51+
friend class options::index;
5052
MONGOCXX_PRIVATE virtual int type() const = 0;
5153
};
5254

@@ -432,6 +434,15 @@ class MONGOCXX_API index {
432434
///
433435
const stdx::optional<double>& haystack_bucket_size() const;
434436

437+
///
438+
/// Conversion operator that provides a view of the options in document form.
439+
///
440+
/// @exception mongocxx::logic_error if an invalid expireAfterSeconds field is provided.
441+
///
442+
/// @return A view of the current builder contents.
443+
///
444+
operator bsoncxx::document::view_or_value();
445+
435446
private:
436447
friend collection;
437448

src/mongocxx/private/libmongoc_symbols.hh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ MONGOCXX_LIBMONGOC_SYMBOL(collection_rename)
6666
MONGOCXX_LIBMONGOC_SYMBOL(collection_set_read_concern)
6767
MONGOCXX_LIBMONGOC_SYMBOL(collection_set_read_prefs)
6868
MONGOCXX_LIBMONGOC_SYMBOL(collection_set_write_concern)
69+
MONGOCXX_LIBMONGOC_SYMBOL(collection_command_simple)
6970
MONGOCXX_LIBMONGOC_SYMBOL(cursor_destroy)
7071
MONGOCXX_LIBMONGOC_SYMBOL(cursor_error)
7172
MONGOCXX_LIBMONGOC_SYMBOL(cursor_new_from_command_reply)

0 commit comments

Comments
 (0)