예제 #1
0
cursor collection::distinct(bsoncxx::string::view_or_value field_name, view_or_value query,
                            const options::distinct& options) {
    bsoncxx::builder::stream::document command_builder{};
    command_builder << "distinct" << name() << "key" << field_name.view() << "query"
                    << bsoncxx::types::b_document{query};

    if (options.max_time()) {
        command_builder << "maxTimeMS" << options.max_time()->count();
    }

    scoped_bson_t command_bson{command_builder.extract()};

    auto database = libmongoc::client_get_database(_get_impl().client_impl->client_t,
                                                   _get_impl().database_name.c_str());

    auto result = libmongoc::database_command(database, MONGOC_QUERY_NONE, 0, 0, 0,
                                              command_bson.bson(), NULL, NULL);

    return cursor(result);
}
예제 #2
0
cursor collection::distinct(bsoncxx::string::view_or_value field_name,
                            view_or_value query,
                            const options::distinct& options) {
    //
    // Construct the distinct command and options.
    //
    bsoncxx::builder::basic::document command_builder;
    command_builder.append(kvp("distinct", name()),
                           kvp("key", field_name.view()),
                           kvp("query", bsoncxx::types::b_document{query}));

    if (options.max_time()) {
        command_builder.append(
            kvp("maxTimeMS", bsoncxx::types::b_int64{options.max_time()->count()}));
    }

    bsoncxx::builder::basic::document opts_builder{};
    if (options.collation()) {
        opts_builder.append(kvp("collation", *options.collation()));
    }

    const mongoc_read_prefs_t* rp_ptr = NULL;
    if (options.read_preference()) {
        rp_ptr = options.read_preference()->_impl->read_preference_t;
    }

    //
    // Send the command and validate the reply.
    //
    scoped_bson_t reply;
    reply.flag_init();
    bson_error_t error;
    scoped_bson_t command_bson{command_builder.extract()};
    scoped_bson_t opts_bson{opts_builder.extract()};

    auto result = libmongoc::collection_read_command_with_opts(_get_impl().collection_t,
                                                               command_bson.bson(),
                                                               rp_ptr,
                                                               opts_bson.bson(),
                                                               reply.bson(),
                                                               &error);

    if (!result) {
        throw_exception<operation_exception>(error);
    }

    //
    // Fake a cursor with the reply document as a single result.
    //
    auto fake_db_reply = make_document(
        kvp("ok", 1), kvp("cursor", [&reply](sub_document sub_doc) {
            sub_doc.append(
                kvp("ns", ""), kvp("id", 0), kvp("firstBatch", [&reply](sub_array sub_arr) {
                    sub_arr.append(reply.view());
                }));
        }));

    bson_t* reply_bson =
        bson_new_from_data(fake_db_reply.view().data(), fake_db_reply.view().length());
    if (!reply_bson) {
        throw bsoncxx::exception{bsoncxx::error_code::k_internal_error};
    }

    cursor fake_cursor{
        libmongoc::cursor_new_from_command_reply(_get_impl().client_impl->client_t, reply_bson, 0)};
    if (libmongoc::cursor_error(fake_cursor._impl->cursor_t, &error)) {
        throw_exception<operation_exception>(error);
    }

    return fake_cursor;
}