Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 6 additions & 18 deletions core/impl/scope.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -161,24 +161,6 @@ scope::analytics_query(std::string statement, const analytics_options& options)
return future;
}

void
scope::search_query(std::string index_name, const class search_query& query, const search_options& options, search_handler&& handler) const
{
return impl_->search_query(std::move(index_name), query, options.build(), std::move(handler));
}

auto
scope::search_query(std::string index_name, const class search_query& query, const search_options& options) const
-> std::future<std::pair<search_error_context, search_result>>
{
auto barrier = std::make_shared<std::promise<std::pair<search_error_context, search_result>>>();
auto future = barrier->get_future();
search_query(std::move(index_name), query, options, [barrier](auto ctx, auto result) {
barrier->set_value({ std::move(ctx), std::move(result) });
});
return future;
}

void
scope::search(std::string index_name, search_request request, const search_options& options, search_handler&& handler) const
{
Expand All @@ -196,4 +178,10 @@ scope::search(std::string index_name, search_request request, const search_optio
});
return future;
}

auto
scope::search_indexes() const -> scope_search_index_manager
{
return scope_search_index_manager{ impl_->core(), impl_->bucket_name(), impl_->name() };
}
} // namespace couchbase
13 changes: 9 additions & 4 deletions core/impl/search.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@

#include <couchbase/cluster.hxx>
#include <couchbase/match_none_query.hxx>
#include <utility>

#include <fmt/core.h>

Expand Down Expand Up @@ -124,8 +125,8 @@ core::operations::search_request
build_search_request(std::string index_name,
const search_query& query,
search_options::built options,
std::optional<std::string> /* bucket_name */,
std::optional<std::string> /* scope_name */)
std::optional<std::string> bucket_name,
std::optional<std::string> scope_name)
{
auto encoded = query.encode();
if (encoded.ec) {
Expand All @@ -134,6 +135,8 @@ build_search_request(std::string index_name,
core::operations::search_request request{
std::move(index_name),
core::utils::json::generate_binary(encoded.query),
std::move(bucket_name),
std::move(scope_name),
{},
{},
{},
Expand Down Expand Up @@ -162,8 +165,8 @@ core::operations::search_request
build_search_request(std::string index_name,
couchbase::search_request request,
search_options::built options,
std::optional<std::string> /* bucket_name */,
std::optional<std::string> /* scope_name */)
std::optional<std::string> bucket_name,
std::optional<std::string> scope_name)
{
if (!request.search_query().has_value()) {
request.search_query(couchbase::match_none_query{});
Expand All @@ -172,6 +175,8 @@ build_search_request(std::string index_name,
core::operations::search_request core_request{
std::move(index_name),
core::utils::json::generate_binary(request.search_query().value().query),
std::move(bucket_name),
std::move(scope_name),
false,
{},
{},
Expand Down
279 changes: 261 additions & 18 deletions core/impl/search_index_manager.cxx

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions core/meta/features.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -106,3 +106,8 @@
* Vector search is supported via couchbase::cluster::search() or couchbase::scope::search()
*/
#define COUCHBASE_CXX_CLIENT_HAS_VECTOR_SEARCH 1

/**
* Scope level search index management is supported via couchbase::scope::search_indexes()
*/
#define COUCHBASE_CXX_CLIENT_HAS_SCOPE_SEARCH_INDEX_MANAGEMENT 1
7 changes: 6 additions & 1 deletion core/operations/document_search.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -122,10 +122,15 @@ search_request::encode_to(search_request::encoded_request_type& encoded, http_co
body[key] = utils::json::parse(value);
}

if (bucket_name.has_value() && scope_name.has_value()) {
encoded.path = fmt::format("/api/bucket/{}/scope/{}/index/{}/query", bucket_name.value(), scope_name.value(), index_name);
} else {
encoded.path = fmt::format("/api/index/{}/query", index_name);
}

encoded.type = type;
encoded.headers["content-type"] = "application/json";
encoded.method = "POST";
encoded.path = fmt::format("/api/index/{}/query", index_name);
body_str = utils::json::generate(body);
encoded.body = body_str;
if (context.options.show_queries) {
Expand Down
2 changes: 2 additions & 0 deletions core/operations/document_search.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,8 @@ struct search_request {

std::string index_name;
couchbase::core::json_string query;
std::optional<std::string> bucket_name;
std::optional<std::string> scope_name;

/**
* UNCOMMITTED: This should be set to false if using the .search() API, leave unset for old .search_query() API
Expand Down
18 changes: 17 additions & 1 deletion core/operations/management/search_index_analyze_document.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,11 @@ search_index_analyze_document_request::encode_to(encoded_request_type& encoded,
encoded.method = "POST";
encoded.headers["cache-control"] = "no-cache";
encoded.headers["content-type"] = "application/json";
encoded.path = fmt::format("/api/index/{}/analyzeDoc", index_name);
if (bucket_name.has_value() && scope_name.has_value()) {
encoded.path = fmt::format("/api/bucket/{}/scope/{}/index/{}/analyzeDoc", bucket_name.value(), scope_name.value(), index_name);
} else {
encoded.path = fmt::format("/api/index/{}/analyzeDoc", index_name);
}
encoded.body = encoded_document;
return {};
}
Expand Down Expand Up @@ -78,6 +82,18 @@ search_index_analyze_document_request::make_response(error_context::http&& ctx,
response.ctx.ec = errc::common::index_exists;
return response;
}
} else if (encoded.status_code == 404) {
tao::json::value payload{};
try {
payload = utils::json::parse(encoded.body.data());
} catch (const tao::pegtl::parse_error&) {
response.ctx.ec = errc::common::parsing_failure;
return response;
}
response.status = payload.at("status").get_string();
response.error = payload.at("error").get_string();
response.ctx.ec = errc::common::feature_not_available;
return response;
}
response.ctx.ec = extract_common_error_code(encoded.status_code, encoded.body.data());
}
Expand Down
3 changes: 3 additions & 0 deletions core/operations/management/search_index_analyze_document.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ struct search_index_analyze_document_request {
std::string index_name;
std::string encoded_document;

std::optional<std::string> bucket_name;
std::optional<std::string> scope_name;

std::optional<std::string> client_context_id{};
std::optional<std::chrono::milliseconds> timeout{};

Expand Down
22 changes: 21 additions & 1 deletion core/operations/management/search_index_control_ingest.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,15 @@ search_index_control_ingest_request::encode_to(encoded_request_type& encoded, ht
return errc::common::invalid_argument;
}
encoded.method = "POST";
encoded.path = fmt::format("/api/index/{}/ingestControl/{}", index_name, pause ? "pause" : "resume");
if (bucket_name.has_value() && scope_name.has_value()) {
encoded.path = fmt::format("/api/bucket/{}/scope/{}/index/{}/ingestControl/{}",
bucket_name.value(),
scope_name.value(),
index_name,
pause ? "pause" : "resume");
} else {
encoded.path = fmt::format("/api/index/{}/ingestControl/{}", index_name, pause ? "pause" : "resume");
}
return {};
}

Expand Down Expand Up @@ -66,6 +74,18 @@ search_index_control_ingest_request::make_response(error_context::http&& ctx, co
response.ctx.ec = errc::common::index_not_found;
return response;
}
} else if (encoded.status_code == 404) {
tao::json::value payload{};
try {
payload = utils::json::parse(encoded.body.data());
} catch (const tao::pegtl::parse_error&) {
response.ctx.ec = errc::common::parsing_failure;
return response;
}
response.status = payload.at("status").get_string();
response.error = payload.at("error").get_string();
response.ctx.ec = errc::common::feature_not_available;
return response;
}
response.ctx.ec = extract_common_error_code(encoded.status_code, encoded.body.data());
}
Expand Down
3 changes: 3 additions & 0 deletions core/operations/management/search_index_control_ingest.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ struct search_index_control_ingest_request {
std::string index_name;
bool pause;

std::optional<std::string> bucket_name;
std::optional<std::string> scope_name;

std::optional<std::string> client_context_id{};
std::optional<std::chrono::milliseconds> timeout{};

Expand Down
22 changes: 21 additions & 1 deletion core/operations/management/search_index_control_plan_freeze.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,15 @@ search_index_control_plan_freeze_request::encode_to(encoded_request_type& encode
return errc::common::invalid_argument;
}
encoded.method = "POST";
encoded.path = fmt::format("/api/index/{}/planFreezeControl/{}", index_name, freeze ? "freeze" : "unfreeze");
if (bucket_name.has_value() && scope_name.has_value()) {
encoded.path = fmt::format("/api/bucket/{}/scope/{}/index/{}/planFreezeControl/{}",
bucket_name.value(),
scope_name.value(),
index_name,
freeze ? "freeze" : "unfreeze");
} else {
encoded.path = fmt::format("/api/index/{}/planFreezeControl/{}", index_name, freeze ? "freeze" : "unfreeze");
}
return {};
}

Expand Down Expand Up @@ -66,6 +74,18 @@ search_index_control_plan_freeze_request::make_response(error_context::http&& ct
response.ctx.ec = errc::common::index_not_found;
return response;
}
} else if (encoded.status_code == 404) {
tao::json::value payload{};
try {
payload = utils::json::parse(encoded.body.data());
} catch (const tao::pegtl::parse_error&) {
response.ctx.ec = errc::common::parsing_failure;
return response;
}
response.status = payload.at("status").get_string();
response.error = payload.at("error").get_string();
response.ctx.ec = errc::common::feature_not_available;
return response;
}
response.ctx.ec = extract_common_error_code(encoded.status_code, encoded.body.data());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ struct search_index_control_plan_freeze_request {
std::string index_name;
bool freeze;

std::optional<std::string> bucket_name;
std::optional<std::string> scope_name;

std::optional<std::string> client_context_id{};
std::optional<std::chrono::milliseconds> timeout{};

Expand Down
22 changes: 21 additions & 1 deletion core/operations/management/search_index_control_query.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,15 @@ search_index_control_query_request::encode_to(encoded_request_type& encoded, htt
return errc::common::invalid_argument;
}
encoded.method = "POST";
encoded.path = fmt::format("/api/index/{}/queryControl/{}", index_name, allow ? "allow" : "disallow");
if (bucket_name.has_value() && scope_name.has_value()) {
encoded.path = fmt::format("/api/bucket/{}/scope/{}/index/{}/queryControl/{}",
bucket_name.value(),
scope_name.value(),
index_name,
allow ? "allow" : "disallow");
} else {
encoded.path = fmt::format("/api/index/{}/queryControl/{}", index_name, allow ? "allow" : "disallow");
}
return {};
}

Expand Down Expand Up @@ -66,6 +74,18 @@ search_index_control_query_request::make_response(error_context::http&& ctx, con
response.ctx.ec = errc::common::index_not_found;
return response;
}
} else if (encoded.status_code == 404) {
tao::json::value payload{};
try {
payload = utils::json::parse(encoded.body.data());
} catch (const tao::pegtl::parse_error&) {
response.ctx.ec = errc::common::parsing_failure;
return response;
}
response.status = payload.at("status").get_string();
response.error = payload.at("error").get_string();
response.ctx.ec = errc::common::feature_not_available;
return response;
}
response.ctx.ec = extract_common_error_code(encoded.status_code, encoded.body.data());
}
Expand Down
3 changes: 3 additions & 0 deletions core/operations/management/search_index_control_query.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ struct search_index_control_query_request {
std::string index_name;
bool allow;

std::optional<std::string> bucket_name;
std::optional<std::string> scope_name;

std::optional<std::string> client_context_id{};
std::optional<std::chrono::milliseconds> timeout{};

Expand Down
18 changes: 17 additions & 1 deletion core/operations/management/search_index_drop.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,11 @@ search_index_drop_request::encode_to(encoded_request_type& encoded, http_context
return errc::common::invalid_argument;
}
encoded.method = "DELETE";
encoded.path = fmt::format("/api/index/{}", index_name);
if (bucket_name.has_value() && scope_name.has_value()) {
encoded.path = fmt::format("/api/bucket/{}/scope/{}/index/{}", bucket_name.value(), scope_name.value(), index_name);
} else {
encoded.path = fmt::format("/api/index/{}", index_name);
}
return {};
}
search_index_drop_response
Expand Down Expand Up @@ -65,6 +69,18 @@ search_index_drop_request::make_response(error_context::http&& ctx, const encode
response.ctx.ec = errc::common::index_not_found;
return response;
}
} else if (encoded.status_code == 404) {
tao::json::value payload{};
try {
payload = utils::json::parse(encoded.body.data());
} catch (const tao::pegtl::parse_error&) {
response.ctx.ec = errc::common::parsing_failure;
return response;
}
response.status = payload.at("status").get_string();
response.error = payload.at("error").get_string();
response.ctx.ec = errc::common::feature_not_available;
return response;
}
response.ctx.ec = extract_common_error_code(encoded.status_code, encoded.body.data());
}
Expand Down
3 changes: 3 additions & 0 deletions core/operations/management/search_index_drop.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ struct search_index_drop_request {

std::string index_name;

std::optional<std::string> bucket_name;
std::optional<std::string> scope_name;

std::optional<std::string> client_context_id{};
std::optional<std::chrono::milliseconds> timeout{};

Expand Down
18 changes: 17 additions & 1 deletion core/operations/management/search_index_get.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,11 @@ search_index_get_request::encode_to(encoded_request_type& encoded, http_context&
return errc::common::invalid_argument;
}
encoded.method = "GET";
encoded.path = fmt::format("/api/index/{}", index_name);
if (bucket_name.has_value() && scope_name.has_value()) {
encoded.path = fmt::format("/api/bucket/{}/scope/{}/index/{}", bucket_name.value(), scope_name.value(), index_name);
} else {
encoded.path = fmt::format("/api/index/{}", index_name);
}
return {};
}

Expand Down Expand Up @@ -68,6 +72,18 @@ search_index_get_request::make_response(error_context::http&& ctx, const encoded
response.ctx.ec = errc::common::index_not_found;
return response;
}
} else if (encoded.status_code == 404) {
tao::json::value payload{};
try {
payload = utils::json::parse(encoded.body.data());
} catch (const tao::pegtl::parse_error&) {
response.ctx.ec = errc::common::parsing_failure;
return response;
}
response.status = payload.at("status").get_string();
response.error = payload.at("error").get_string();
response.ctx.ec = errc::common::feature_not_available;
return response;
}
response.ctx.ec = extract_common_error_code(encoded.status_code, encoded.body.data());
}
Expand Down
2 changes: 2 additions & 0 deletions core/operations/management/search_index_get.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ struct search_index_get_request {
static const inline service_type type = service_type::search;

std::string index_name;
std::optional<std::string> bucket_name;
std::optional<std::string> scope_name;

std::optional<std::string> client_context_id{};
std::optional<std::chrono::milliseconds> timeout{};
Expand Down
Loading