diff --git a/src/core_api.cpp b/src/core_api.cpp index 0cc9e496..d0856158 100644 --- a/src/core_api.cpp +++ b/src/core_api.cpp @@ -1498,6 +1498,12 @@ bool patch_update_documents(const std::shared_ptr& req, const std::sha bool get_fetch_document(const std::shared_ptr& req, const std::shared_ptr& res) { std::string doc_id = req->params["id"]; + const char* INCLUDE_FIELDS = "include_fields"; + const char* EXCLUDE_FIELDS = "exclude_fields"; + + spp::sparse_hash_set exclude_fields; + spp::sparse_hash_set 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& 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 include_fields_vec; + StringUtils::split(req->params[INCLUDE_FIELDS], include_fields_vec, ","); + include_fields = spp::sparse_hash_set(include_fields_vec.begin(), include_fields_vec.end()); + } + + if(req->params.count(EXCLUDE_FIELDS) != 0) { + std::vector exclude_fields_vec; + StringUtils::split(req->params[EXCLUDE_FIELDS], exclude_fields_vec, ","); + exclude_fields = spp::sparse_hash_set(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; } diff --git a/test/core_api_utils_test.cpp b/test/core_api_utils_test.cpp index 42109911..c28a876e 100644 --- a/test/core_api_utils_test.cpp +++ b/test/core_api_utils_test.cpp @@ -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 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 req = std::make_shared(); + std::shared_ptr res = std::make_shared(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")); } \ No newline at end of file