add support for include exclude fields in doc fetch (#1782)

Co-authored-by: Kishore Nallan <kishorenc@gmail.com>
This commit is contained in:
Krunal Gandhi 2024-06-12 04:03:14 +00:00 committed by GitHub
parent e1615dddf8
commit 2f16a71d98
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 115 additions and 1 deletions

View File

@ -1498,6 +1498,12 @@ bool patch_update_documents(const std::shared_ptr<http_req>& req, const std::sha
bool get_fetch_document(const std::shared_ptr<http_req>& req, const std::shared_ptr<http_res>& res) {
std::string doc_id = req->params["id"];
const char* INCLUDE_FIELDS = "include_fields";
const char* EXCLUDE_FIELDS = "exclude_fields";
spp::sparse_hash_set<std::string> exclude_fields;
spp::sparse_hash_set<std::string> include_fields;
CollectionManager & collectionManager = CollectionManager::get_instance();
auto collection = collectionManager.get_collection(req->params["collection"]);
if(collection == nullptr) {
@ -1512,7 +1518,34 @@ bool get_fetch_document(const std::shared_ptr<http_req>& req, const std::shared_
return false;
}
res->set_200(doc_option.get().dump(-1, ' ', false, nlohmann::detail::error_handler_t::ignore));
if(req->params.count(INCLUDE_FIELDS) != 0) {
std::vector<std::string> include_fields_vec;
StringUtils::split(req->params[INCLUDE_FIELDS], include_fields_vec, ",");
include_fields = spp::sparse_hash_set<std::string>(include_fields_vec.begin(), include_fields_vec.end());
}
if(req->params.count(EXCLUDE_FIELDS) != 0) {
std::vector<std::string> exclude_fields_vec;
StringUtils::split(req->params[EXCLUDE_FIELDS], exclude_fields_vec, ",");
exclude_fields = spp::sparse_hash_set<std::string>(exclude_fields_vec.begin(), exclude_fields_vec.end());
}
nlohmann::json doc = doc_option.get();
for(auto it = doc.begin(); it != doc.end(); ++it) {
if(!include_fields.empty() && include_fields.count(it.key()) == 0) {
doc.erase(it.key());
continue;
}
if(!exclude_fields.empty() && exclude_fields.count(it.key()) != 0) {
doc.erase(it.key());
continue;
}
}
res->set_200(doc.dump(-1, ' ', false, nlohmann::detail::error_handler_t::ignore));
return true;
}

View File

@ -2071,4 +2071,85 @@ TEST_F(CoreAPIUtilsTest, CollectionUpdateValidation) {
req->body = alter_schema.dump();
ASSERT_FALSE(patch_update_collection(req, res));
ASSERT_EQ("{\"message\": \"Alter payload is empty.\"}", res->body);
}
TEST_F(CoreAPIUtilsTest, DocumentGetIncludeExcludeFields) {
std::vector<field> fields = {
field("title", field_types::STRING, false),
field("brand", field_types::STRING, true, true),
field("size", field_types::INT32, true, false),
field("colors", field_types::STRING_ARRAY, true, false),
field("rating", field_types::FLOAT, true, false)
};
auto coll1 = collectionManager.get_collection("coll1").get();
if(coll1 == nullptr) {
coll1 = collectionManager.create_collection("coll1", 4, fields, "rating").get();
}
nlohmann::json doc;
doc["id"] = "1";
doc["title"] = "Denim jeans";
doc["brand"] = "Spykar";
doc["size"] = 40;
doc["colors"] = {"blue", "black", "grey"};
doc["rating"] = 4.5;
coll1->add(doc.dump());
doc["id"] = "2";
doc["title"] = "Denim jeans";
doc["brand"] = "Levis";
doc["size"] = 42;
doc["colors"] = {"blue", "black"};
doc["rating"] = 4.4;
coll1->add(doc.dump());
std::shared_ptr<http_req> req = std::make_shared<http_req>();
std::shared_ptr<http_res> res = std::make_shared<http_res>(nullptr);
req->params["collection"] = "coll1";
req->params["id"] = "1";
//normal doc fetch
ASSERT_TRUE(get_fetch_document(req, res));
auto resp = nlohmann::json::parse(res->body);
ASSERT_EQ(6, resp.size());
ASSERT_TRUE(resp.contains("brand"));
ASSERT_TRUE(resp.contains("size"));
ASSERT_TRUE(resp.contains("colors"));
ASSERT_TRUE(resp.contains("rating"));
ASSERT_TRUE(resp.contains("id"));
ASSERT_TRUE(resp.contains("title"));
//include fields
req->params["include_fields"] = "brand,size,colors";
ASSERT_TRUE(get_fetch_document(req, res));
resp = nlohmann::json::parse(res->body);
ASSERT_EQ(3, resp.size());
ASSERT_TRUE(resp.contains("brand"));
ASSERT_TRUE(resp.contains("size"));
ASSERT_TRUE(resp.contains("colors"));
ASSERT_FALSE(resp.contains("rating"));
//exclude fields
req->params.erase("include_fields");
req->params["exclude_fields"] = "brand,size,colors";
ASSERT_TRUE(get_fetch_document(req, res));
resp = nlohmann::json::parse(res->body);
ASSERT_EQ(3, resp.size());
ASSERT_TRUE(resp.contains("id"));
ASSERT_TRUE(resp.contains("title"));
ASSERT_TRUE(resp.contains("rating"));
ASSERT_FALSE(resp.contains("brand"));
//both include and exclude fields
req->params["include_fields"] = "title,rating";
req->params["exclude_fields"] = "brand,size,colors";
ASSERT_TRUE(get_fetch_document(req, res));
resp = nlohmann::json::parse(res->body);
ASSERT_EQ(2, resp.size());
ASSERT_TRUE(resp.contains("title"));
ASSERT_TRUE(resp.contains("rating"));
ASSERT_FALSE(resp.contains("id"));
}