Merge branch 'v0.24-nested' into v0.25

This commit is contained in:
Kishore Nallan 2023-01-18 10:41:51 +05:30
commit 3e774e6f77
5 changed files with 182 additions and 5 deletions

View File

@ -261,8 +261,15 @@ Option<bool> CollectionManager::load(const size_t collection_batch_size, const s
iter = store->scan(preset_prefix_key, &preset_upper_bound);
while(iter->Valid() && iter->key().starts_with(preset_prefix_key)) {
std::vector<std::string> parts;
StringUtils::split(iter->key().ToString(), parts, preset_prefix_key);
preset_configs[parts[0]] = iter->value().ToString();
std::string preset_name = iter->key().ToString().substr(preset_prefix_key.size());
nlohmann::json preset_obj = nlohmann::json::parse(iter->value().ToString(), nullptr, false);
if(!preset_obj.is_discarded() && preset_obj.is_object()) {
preset_configs[preset_name] = preset_obj;
} else {
LOG(INFO) << "Invalid value for preset " << preset_name;
}
iter->Next();
}

View File

@ -93,6 +93,17 @@ void get_collections_for_auth(std::map<std::string, std::string>& req_params,
coll_name = el["collection"].get<std::string>();
} else if(req_params.count("collection") != 0) {
coll_name = req_params["collection"];
} else {
// if preset exists, that should be the lowest priority
if(el.count("preset") != 0) {
nlohmann::json preset_obj;
auto preset_op = CollectionManager::get_instance().
get_preset(el["preset"].get<std::string>(), preset_obj);
if(preset_op.ok() && preset_obj.count("collection") != 0 &&
preset_obj["collection"].is_string()) {
coll_name = preset_obj["collection"].get<std::string>();
}
}
}
const std::string& access_key = (el.count("x-typesense-api-key") != 0 &&
@ -523,6 +534,27 @@ bool post_multi_search(const std::shared_ptr<http_req>& req, const std::shared_p
}
}
if(search_params.count("preset") != 0) {
nlohmann::json preset;
auto preset_op = CollectionManager::get_instance().get_preset(search_params["preset"].get<std::string>(),
preset);
if(preset_op.ok()) {
if(!search_params.is_object()) {
res->set_400("Search preset is not an object.");
return false;
}
for(const auto& search_item: preset.items()) {
// overwrite = false since req params will contain embedded params and so has higher priority
bool populated = AuthManager::add_item_to_params(req->params, search_item, false);
if(!populated) {
res->set_400("One or more search parameters are malformed.");
return false;
}
}
}
}
std::string results_json_str;
Option<bool> search_op = CollectionManager::do_search(req->params, req->embedded_params_vec[i],
results_json_str, req->conn_ts);

View File

@ -660,6 +660,32 @@ TEST_F(CollectionManagerTest, RestoreAutoSchemaDocsOnRestart) {
collectionManager2.drop_collection("coll1");
}
TEST_F(CollectionManagerTest, RestorePresetsOnRestart) {
auto preset_value = R"(
{"q":"*", "per_page": "12"}
)"_json;
collectionManager.upsert_preset("single_preset", preset_value);
// create a new collection manager to ensure that it restores the records from the disk backed store
CollectionManager& collectionManager2 = CollectionManager::get_instance();
collectionManager2.init(store, 1.0, "auth_key", quit);
auto load_op = collectionManager2.load(8, 1000);
if(!load_op.ok()) {
LOG(ERROR) << load_op.error();
}
ASSERT_TRUE(load_op.ok());
nlohmann::json preset;
collectionManager2.get_preset("single_preset", preset);
ASSERT_EQ("*", preset["q"].get<std::string>());
collectionManager.drop_collection("coll1");
collectionManager2.drop_collection("coll1");
}
TEST_F(CollectionManagerTest, RestoreNestedDocsOnRestart) {
nlohmann::json schema = R"({
"name": "coll1",

View File

@ -2125,6 +2125,32 @@ TEST_F(CollectionNestedFieldsTest, ErrorWhenObjectTypeUsedWithoutEnablingNestedF
"enable_nested_fields` to true.", op.error());
}
TEST_F(CollectionNestedFieldsTest, FieldsWithDotsButNotNested) {
nlohmann::json schema = R"({
"name": "coll1",
"enable_nested_fields": true,
"fields": [
{"name": "name.first", "type": "string"}
]
})"_json;
auto op = collectionManager.create_collection(schema);
ASSERT_TRUE(op.ok());
Collection* coll1 = op.get();
auto doc1 = R"({
"name.first": "Alpha Beta Gamma"
})"_json;
auto add_op = coll1->add(doc1.dump(), CREATE);
ASSERT_TRUE(add_op.ok());
auto results = coll1->search("beta", {"name.first"}, "", {}, {}, {0}, 10, 1, FREQUENCY, {false}).get();
ASSERT_EQ(1, results["found"].get<size_t>());
ASSERT_EQ("Alpha <mark>Beta</mark> Gamma",
results["hits"][0]["highlight"]["name.first"]["snippet"].get<std::string>());
}
TEST_F(CollectionNestedFieldsTest, UpdateNestedDocument) {
nlohmann::json schema = R"({
"name": "coll1",

View File

@ -491,7 +491,7 @@ TEST_F(CoreAPIUtilsTest, MultiSearchWithPresetShouldUsePresetForAuth) {
std::vector<collection_key_t> collections;
std::vector<nlohmann::json> embedded_params_vec;
std::string other_body = R"(
std::string search_body = R"(
{"searches":[
{"collection":"foo1","q":"apple", "query_by": "title"},
{"collection":"bar1","q":"apple", "query_by": "title"}
@ -500,7 +500,7 @@ TEST_F(CoreAPIUtilsTest, MultiSearchWithPresetShouldUsePresetForAuth) {
// without preset parameter, use collections from request body
get_collections_for_auth(req_params, other_body, rpath_multi_search, "", collections, embedded_params_vec);
get_collections_for_auth(req_params, search_body, rpath_multi_search, "", collections, embedded_params_vec);
ASSERT_EQ(2, collections.size());
ASSERT_EQ("foo1", collections[0].collection);
@ -512,12 +512,98 @@ TEST_F(CoreAPIUtilsTest, MultiSearchWithPresetShouldUsePresetForAuth) {
embedded_params_vec.clear();
req_params["preset"] = "apple";
get_collections_for_auth(req_params, other_body, rpath_multi_search, "", collections, embedded_params_vec);
get_collections_for_auth(req_params, search_body, rpath_multi_search, "", collections, embedded_params_vec);
ASSERT_EQ(2, collections.size());
ASSERT_EQ("foo", collections[0].collection);
ASSERT_EQ("bar", collections[1].collection);
ASSERT_EQ(2, embedded_params_vec.size());
// try using multi_search preset within individual search param
preset_value = R"(
{"collection":"preset_coll"}
)"_json;
collectionManager.upsert_preset("single_preset", preset_value);
req_params.clear();
collections.clear();
embedded_params_vec.clear();
search_body = R"(
{"searches":[
{"collection":"foo1","q":"apple", "query_by": "title", "preset": "single_preset"},
{"collection":"bar1","q":"apple", "query_by": "title", "preset": "single_preset"}
]}
)";
get_collections_for_auth(req_params, search_body, rpath_multi_search, "", collections, embedded_params_vec);
ASSERT_EQ(2, collections.size());
ASSERT_EQ("foo1", collections[0].collection);
ASSERT_EQ("bar1", collections[1].collection);
ASSERT_EQ(2, embedded_params_vec.size());
// without collection in search array
req_params.clear();
collections.clear();
embedded_params_vec.clear();
search_body = R"(
{"searches":[
{"q":"apple", "query_by": "title", "preset": "single_preset"},
{"q":"apple", "query_by": "title", "preset": "single_preset"}
]}
)";
get_collections_for_auth(req_params, search_body, rpath_multi_search, "", collections, embedded_params_vec);
ASSERT_EQ(2, collections.size());
ASSERT_EQ("preset_coll", collections[0].collection);
ASSERT_EQ("preset_coll", collections[1].collection);
ASSERT_EQ(2, embedded_params_vec.size());
}
TEST_F(CoreAPIUtilsTest, PresetSingleSearch) {
nlohmann::json schema = R"({
"name": "coll1",
"fields": [
{"name": "name", "type": "string" },
{"name": "points", "type": "int32" }
]
})"_json;
auto op = collectionManager.create_collection(schema);
ASSERT_TRUE(op.ok());
Collection* coll1 = op.get();
auto preset_value = R"(
{"collection":"preset_coll", "per_page": "12"}
)"_json;
collectionManager.upsert_preset("single_preset", preset_value);
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";
auto search_body = R"(
{"searches":[
{"collection":"coll1","q":"apple", "query_by": "title", "preset": "single_preset"}
]}
)";
req->body = search_body;
nlohmann::json embedded_params;
req->embedded_params_vec.push_back(embedded_params);
post_multi_search(req, res);
ASSERT_EQ("12", req->params["per_page"]);
ASSERT_EQ("coll1", req->params["collection"]);
collectionManager.drop_collection("coll1");
}
TEST_F(CoreAPIUtilsTest, ExportWithFilter) {