Update reference include_fields syntax. (#1636)

This commit is contained in:
Harpreet Sangar 2024-03-27 16:23:54 +05:30 committed by GitHub
parent b666244ce1
commit f05c113e65
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 143 additions and 105 deletions

View File

@ -531,6 +531,7 @@ namespace sort_field_const {
}
namespace ref_include {
static const std::string strategy_key = "strategy";
static const std::string merge_string = "merge";
static const std::string nest_string = "nest";
static const std::string nest_array_string = "nest_array";

View File

@ -1113,10 +1113,37 @@ Option<bool> parse_nested_exclude(const std::string& exclude_field_exp,
return Option<bool>(true);
}
Option<bool> parse_ref_include_parameters(const std::string& include_field_exp, const std::string& parameters,
ref_include::strategy_enum& strategy_enum) {
std::vector<std::string> parameters_map;
StringUtils::split(parameters, parameters_map, ",");
for (const auto &item: parameters_map) {
std::vector<std::string> parameter_pair;
StringUtils::split(item, parameter_pair, ":");
if (parameter_pair.size() != 2) {
continue;
}
auto const& key = StringUtils::trim(parameter_pair[0]);
if (key == ref_include::strategy_key) {
auto const& include_strategy = StringUtils::trim(parameter_pair[1]);
auto string_to_enum_op = ref_include::string_to_enum(include_strategy);
if (!string_to_enum_op.ok()) {
return Option<bool>(400, "Error parsing `" + include_field_exp + "`: " + string_to_enum_op.error());
}
strategy_enum = string_to_enum_op.get();
} else {
return Option<bool>(400, "Unknown reference `include_fields` parameter: `" + key + "`.");
}
}
return Option<bool>(true);
}
Option<bool> parse_nested_include(const std::string& include_field_exp,
CollectionManager::ref_include_collection_names_t* const ref_include_coll_names,
std::vector<ref_include_exclude_fields>& ref_include_exclude_fields_vec) {
// Format: $ref_collection_name(field_1, field_2, $nested_ref_coll(nested_field_1: nested_include_strategy) as nested_ref_alias: include_strategy) as ref_alias
// Format: $ref_collection_name(field_1, field_2, $nested_ref_coll(nested_field_1, strategy: nested_include_strategy) as nested_ref_alias, strategy: include_strategy) as ref_alias
size_t index = 0;
while (index < include_field_exp.size()) {
auto parenthesis_index = include_field_exp.find('(');
@ -1132,7 +1159,7 @@ Option<bool> parse_nested_include(const std::string& include_field_exp,
std::vector<ref_include_exclude_fields> nested_ref_include_exclude_fields_vec;
if (nested_include_pos < closing_parenthesis_pos) {
// Nested reference include.
// "... $product_variants(title, $inventory(qty:merge) as inventory :nest) as variants ..."
// "... $product_variants(title, $inventory(qty, strategy:merge) as inventory, strategy :nest) as variants ..."
do {
ref_fields += include_field_exp.substr(index, nested_include_pos - index);
StringUtils::trim(ref_fields);
@ -1159,28 +1186,31 @@ Option<bool> parse_nested_include(const std::string& include_field_exp,
} while(index < include_field_exp.size() && nested_include_pos < closing_parenthesis_pos);
}
// ... $inventory(qty:merge) as inventory ...
auto include_strategy = ref_include::nest_string;
auto strategy_enum = ref_include::nest;
if (colon_pos < closing_parenthesis_pos) { // Merge strategy is specified.
include_strategy = include_field_exp.substr(colon_pos + 1, closing_parenthesis_pos - colon_pos - 1);
StringUtils::trim(include_strategy);
auto string_to_enum_op = ref_include::string_to_enum(include_strategy);
if (!string_to_enum_op.ok()) {
return Option<bool>(400, "Error parsing `" + include_field_exp + "`: " + string_to_enum_op.error());
}
strategy_enum = string_to_enum_op.get();
if (index < colon_pos) {
ref_fields += include_field_exp.substr(index, colon_pos - index);
}
} else if (index < closing_parenthesis_pos) {
if (index < closing_parenthesis_pos) {
ref_fields += include_field_exp.substr(index, closing_parenthesis_pos - index);
}
index = closing_parenthesis_pos;
// ... $inventory(qty, strategy:merge) as inventory
auto strategy_enum = ref_include::nest;
if (colon_pos < closing_parenthesis_pos) {
auto const& parameters_start = ref_fields.rfind(',', colon_pos);
std::string parameters;
if (parameters_start == std::string::npos) {
parameters = ref_fields;
ref_fields.clear();
} else {
parameters = ref_fields.substr(parameters_start + 1);
ref_fields = ref_fields.substr(0, parameters_start);
}
auto parse_params_op = parse_ref_include_parameters(include_field_exp, parameters, strategy_enum);
if (!parse_params_op.ok()) {
return parse_params_op;
}
}
StringUtils::trim(ref_fields);
index = closing_parenthesis_pos;
auto as_pos = include_field_exp.find(" as ", index);
comma_pos = include_field_exp.find(',', index);
if (as_pos != std::string::npos && as_pos < comma_pos) {
@ -1250,20 +1280,23 @@ Option<bool> CollectionManager::_initialize_ref_include_exclude_fields_vec(const
auto ref_collection_name = ref_include.substr(1, parenthesis_index - 1);
auto ref_fields = ref_include.substr(parenthesis_index + 1, ref_include.size() - parenthesis_index - 2);
auto include_strategy = ref_include::nest_string;
auto strategy_enum = ref_include::nest;
auto colon_pos = ref_fields.find(':');
if (colon_pos != std::string::npos) {
include_strategy = ref_fields.substr(colon_pos + 1, ref_fields.size() - colon_pos - 1);
StringUtils::trim(include_strategy);
auto string_to_enum_op = ref_include::string_to_enum(include_strategy);
if (!string_to_enum_op.ok()) {
return Option<bool>(400, "Error parsing `" + include_field_exp + "`: " + string_to_enum_op.error());
auto const& parameters_start = ref_fields.rfind(',', colon_pos);
std::string parameters;
if (parameters_start == std::string::npos) {
parameters = ref_fields;
ref_fields.clear();
} else {
parameters = ref_fields.substr(parameters_start + 1);
ref_fields = ref_fields.substr(0, parameters_start);
}
strategy_enum = string_to_enum_op.get();
ref_fields = ref_fields.substr(0, colon_pos);
auto parse_params_op = parse_ref_include_parameters(include_field_exp, parameters, strategy_enum);
if (!parse_params_op.ok()) {
return parse_params_op;
}
}
// For an alias `foo`,

View File

@ -519,17 +519,14 @@ Option<bool> StringUtils::split_reference_include_exclude_fields(const std::stri
}
// In case of nested reference include, we might end up with one of the following scenarios:
// $ref_include( $nested_ref_include(foo :merge)as nest ) as ref
// ...^
// $ref_include( $nested_ref_include(foo :merge)as nest, bar ) as ref
// ...^
// $ref_include( $nested_ref_include(foo :merge)as nest :merge ) as ref
// ...^
// $ref_include( $nested_ref_include(foo, strategy:merge)as nest ) as ref
// ...^
// $ref_include( $nested_ref_include(foo, strategy:merge)as nest, bar ) as ref
// ...^
auto closing_parenthesis_pos = include_exclude_fields.find(')', index);
auto comma_pos = include_exclude_fields.find(',', index);
auto colon_pos = include_exclude_fields.find(':', index);
auto alias_start_pos = include_exclude_fields.find(" as ", index);
auto alias_end_pos = std::min(std::min(closing_parenthesis_pos, comma_pos), colon_pos);
auto alias_end_pos = std::min(closing_parenthesis_pos, comma_pos);
std::string alias;
if (alias_start_pos != std::string::npos && alias_start_pos < alias_end_pos) {
alias = include_exclude_fields.substr(alias_start_pos, alias_end_pos - alias_start_pos);

View File

@ -1336,7 +1336,7 @@ TEST_F(CollectionJoinTest, FilterByReference_SingleMatch) {
{"q", "Dan"},
{"query_by", "customer_name"},
{"filter_by", "$Products(rating:>3)"},
{"include_fields", "$Products(*:merge)"},
{"include_fields", "$Products(*, strategy:merge)"},
};
search_op_bool = collectionManager.do_search(req_params, embedded_params, json_res, now_ts);
@ -1352,7 +1352,7 @@ TEST_F(CollectionJoinTest, FilterByReference_SingleMatch) {
{"q", "Dan"},
{"query_by", "customer_name"},
{"filter_by", "$Products(id:*) && product_price:>100"},
{"include_fields", "$Products(*:merge)"},
{"include_fields", "$Products(*, strategy:merge)"},
};
search_op_bool = collectionManager.do_search(req_params, embedded_params, json_res, now_ts);
@ -2104,7 +2104,7 @@ TEST_F(CollectionJoinTest, FilterByNestedReferences) {
{"collection", "Coll_A"},
{"q", "*"},
{"filter_by", "$Coll_B($Coll_C(id: != 0))"},
{"include_fields", "title, $Coll_B(title, $Coll_C(title):nest_array)"}
{"include_fields", "title, $Coll_B(title, $Coll_C(title), strategy:nest_array)"}
};
search_op = collectionManager.do_search(req_params, embedded_params, json_res, now_ts);
ASSERT_TRUE(search_op.ok());
@ -2208,7 +2208,7 @@ TEST_F(CollectionJoinTest, FilterByNestedReferences) {
{"collection", "Coll_B"},
{"q", "*"},
{"filter_by", "$Coll_C($Coll_D(id: *))"},
{"include_fields", "title, $Coll_C(title, $Coll_D(title:nest_array):nest_array)"}
{"include_fields", "title, $Coll_C(title, $Coll_D(title, strategy:nest_array), strategy:nest_array)"}
};
search_op = collectionManager.do_search(req_params, embedded_params, json_res, now_ts);
ASSERT_TRUE(search_op.ok());
@ -2252,7 +2252,7 @@ TEST_F(CollectionJoinTest, FilterByNestedReferences) {
{"collection", "Coll_D"},
{"q", "*"},
{"filter_by", "$Coll_C($Coll_B(id: [0, 1]))"},
{"include_fields", "title, $Coll_C(title, $Coll_B(title:nest_array):nest_array)"}
{"include_fields", "title, $Coll_C(title, $Coll_B(title, strategy:nest_array), strategy:nest_array)"}
};
search_op = collectionManager.do_search(req_params, embedded_params, json_res, now_ts);
ASSERT_TRUE(search_op.ok());
@ -2677,7 +2677,7 @@ TEST_F(CollectionJoinTest, IncludeExcludeFieldsByReference) {
{"q", "*"},
{"query_by", "product_name"},
{"filter_by", "$Customers(customer_id:=customer_a && product_price:<100)"},
{"include_fields", "*, $Customers(*:nest_array) as Customers"}
{"include_fields", "*, $Customers(*, strategy:nest_array) as Customers"}
};
search_op = collectionManager.do_search(req_params, embedded_params, json_res, now_ts);
ASSERT_TRUE(search_op.ok());
@ -2706,7 +2706,7 @@ TEST_F(CollectionJoinTest, IncludeExcludeFieldsByReference) {
{"q", "*"},
{"query_by", "product_name"},
{"filter_by", "$Customers(customer_id:=customer_a && product_price:<100)"},
{"include_fields", "*, $Customers(*:merge) as Customers"}
{"include_fields", "*, $Customers(*, strategy:merge) as Customers"}
};
search_op = collectionManager.do_search(req_params, embedded_params, json_res, now_ts);
ASSERT_TRUE(search_op.ok());
@ -2731,7 +2731,7 @@ TEST_F(CollectionJoinTest, IncludeExcludeFieldsByReference) {
{"q", "*"},
{"query_by", "product_name"},
{"filter_by", "$Customers(customer_id:=customer_a && product_price:<100)"},
{"include_fields", "$Customers(bar:merge)"}
{"include_fields", "$Customers(bar, strategy:merge)"}
};
search_op = collectionManager.do_search(req_params, embedded_params, json_res, now_ts);
ASSERT_TRUE(search_op.ok());
@ -2753,7 +2753,7 @@ TEST_F(CollectionJoinTest, IncludeExcludeFieldsByReference) {
{"q", "*"},
{"query_by", "product_name"},
{"filter_by", "$Customers(customer_id:=customer_a && product_price:<100)"},
{"include_fields", "$Customers(product_price:merge)"}
{"include_fields", "$Customers(product_price, strategy:merge)"}
};
search_op = collectionManager.do_search(req_params, embedded_params, json_res, now_ts);
ASSERT_TRUE(search_op.ok());
@ -2770,7 +2770,7 @@ TEST_F(CollectionJoinTest, IncludeExcludeFieldsByReference) {
{"q", "*"},
{"query_by", "product_name"},
{"filter_by", "$Customers(customer_id:=customer_a && product_price:<100)"},
{"include_fields", "$Customers(product_price, customer_id:merge)"}
{"include_fields", "$Customers(product_price, customer_id, strategy:merge)"}
};
search_op = collectionManager.do_search(req_params, embedded_params, json_res, now_ts);
ASSERT_TRUE(search_op.ok());
@ -2789,7 +2789,7 @@ TEST_F(CollectionJoinTest, IncludeExcludeFieldsByReference) {
{"q", "*"},
{"query_by", "product_name"},
{"filter_by", "$Customers(customer_id:=customer_a && product_price:<100)"},
{"include_fields", "*, $Customers(product_price, customer_id:merge)"}
{"include_fields", "*, $Customers(product_price, customer_id, strategy:merge)"}
};
search_op = collectionManager.do_search(req_params, embedded_params, json_res, now_ts);
ASSERT_TRUE(search_op.ok());
@ -2805,7 +2805,7 @@ TEST_F(CollectionJoinTest, IncludeExcludeFieldsByReference) {
{"q", "*"},
{"query_by", "product_name"},
{"filter_by", "$Customers(customer_id:=customer_a && product_price:<100)"},
{"include_fields", "$Customers(product*:merge)"}
{"include_fields", "$Customers(product*, strategy:merge)"}
};
search_op = collectionManager.do_search(req_params, embedded_params, json_res, now_ts);
ASSERT_TRUE(search_op.ok());
@ -2822,7 +2822,7 @@ TEST_F(CollectionJoinTest, IncludeExcludeFieldsByReference) {
{"q", "s"},
{"query_by", "product_name"},
{"filter_by", "$Customers(customer_id:=customer_a && product_price:<100)"},
{"include_fields", "$Customers(product*:merge)"},
{"include_fields", "$Customers(product*, strategy:merge)"},
{"exclude_fields", "$Customers(product_id_sequence_id)"}
};
search_op = collectionManager.do_search(req_params, embedded_params, json_res, now_ts);
@ -2883,7 +2883,7 @@ TEST_F(CollectionJoinTest, IncludeExcludeFieldsByReference) {
{"q", "*"},
{"query_by", "product_name"},
{"filter_by", "product_name:soap && $Customers(product_price:>100)"},
{"include_fields", "product_name, $Customers(product_price:merge)"},
{"include_fields", "product_name, $Customers(product_price, strategy:merge)"},
{"exclude_fields", ""}
};
search_op = collectionManager.do_search(req_params, embedded_params, json_res, now_ts);
@ -2904,7 +2904,7 @@ TEST_F(CollectionJoinTest, IncludeExcludeFieldsByReference) {
{"q", "soap"},
{"query_by", "product_name"},
{"filter_by", "$Customers(product_price: >0)"},
{"include_fields", "product_name, $Customers(customer_name, product_price:merge)"},
{"include_fields", "product_name, $Customers(customer_name, product_price, strategy:merge)"},
{"exclude_fields", ""}
};
search_op = collectionManager.do_search(req_params, embedded_params, json_res, now_ts);
@ -2929,7 +2929,7 @@ TEST_F(CollectionJoinTest, IncludeExcludeFieldsByReference) {
{"q", "natural products"},
{"query_by", "embedding"},
{"filter_by", "$Customers(customer_id:=customer_a && product_price:<100)"},
{"include_fields", "product_name, $Customers(product_price:merge)"},
{"include_fields", "product_name, $Customers(product_price, strategy:merge)"},
{"exclude_fields", ""}
};
search_op = collectionManager.do_search(req_params, embedded_params, json_res, now_ts);
@ -2959,7 +2959,7 @@ TEST_F(CollectionJoinTest, IncludeExcludeFieldsByReference) {
{"q", "*"},
{"vector_query", "embedding:(" + vec_string + ", flat_search_cutoff: 0)"},
{"filter_by", "$Customers(customer_id:=customer_a && product_price:<100)"},
{"include_fields", "product_name, $Customers(product_price : merge)"},
{"include_fields", "product_name, $Customers(product_price, strategy : merge)"},
{"exclude_fields", ""}
};
search_op = collectionManager.do_search(req_params, embedded_params, json_res, now_ts);
@ -2979,7 +2979,7 @@ TEST_F(CollectionJoinTest, IncludeExcludeFieldsByReference) {
{"q", "soap"},
{"query_by", "product_name, embedding"},
{"filter_by", "$Customers(customer_id:=customer_a && product_price:<100)"},
{"include_fields", "product_name, $Customers(product_price: merge)"},
{"include_fields", "product_name, $Customers(product_price, strategy: merge)"},
{"exclude_fields", ""}
};
search_op = collectionManager.do_search(req_params, embedded_params, json_res, now_ts);
@ -3001,7 +3001,7 @@ TEST_F(CollectionJoinTest, IncludeExcludeFieldsByReference) {
{"q", "natural products"},
{"query_by", "product_name, embedding"},
{"filter_by", "$Customers(customer_id:=customer_a && product_price:<100)"},
{"include_fields", "product_name, $Customers(product_price :merge)"},
{"include_fields", "product_name, $Customers(product_price , strategy:merge)"},
{"exclude_fields", ""}
};
search_op = collectionManager.do_search(req_params, embedded_params, json_res, now_ts);
@ -3024,7 +3024,7 @@ TEST_F(CollectionJoinTest, IncludeExcludeFieldsByReference) {
{"query_by", "product_name"},
{"infix", "always"},
{"filter_by", "$Customers(customer_id:=customer_a && product_price:<100)"},
{"include_fields", "product_name, $Customers(product_price:merge)"},
{"include_fields", "product_name, $Customers(product_price, strategy:merge)"},
{"exclude_fields", ""}
};
search_op = collectionManager.do_search(req_params, embedded_params, json_res, now_ts);
@ -3044,7 +3044,7 @@ TEST_F(CollectionJoinTest, IncludeExcludeFieldsByReference) {
{"q", "Dan"},
{"query_by", "customer_name"},
{"filter_by", "$Products(rating:>3)"},
{"include_fields", "$Products(product_name:merge), product_price"}
{"include_fields", "$Products(product_name, strategy:merge), product_price"}
};
search_op = collectionManager.do_search(req_params, embedded_params, json_res, now_ts);
@ -3065,7 +3065,7 @@ TEST_F(CollectionJoinTest, IncludeExcludeFieldsByReference) {
{"q", "Joe"},
{"query_by", "customer_name"},
{"filter_by", "product_price:<100"},
{"include_fields", "$Products(product_name: merge), product_price"}
{"include_fields", "$Products(product_name, strategy: merge), product_price"}
};
search_op = collectionManager.do_search(req_params, embedded_params, json_res, now_ts);
ASSERT_TRUE(search_op.ok());
@ -3085,7 +3085,7 @@ TEST_F(CollectionJoinTest, IncludeExcludeFieldsByReference) {
{"q", "soap"},
{"query_by", "product_name"},
{"filter_by", "$Customers(id:*)"},
{"include_fields", "id, $Customers(id :merge)"}
{"include_fields", "id, $Customers(id , strategy:merge)"}
};
search_op = collectionManager.do_search(req_params, embedded_params, json_res, now_ts);
ASSERT_FALSE(search_op.ok());
@ -3097,7 +3097,7 @@ TEST_F(CollectionJoinTest, IncludeExcludeFieldsByReference) {
{"q", "soap"},
{"query_by", "product_name"},
{"filter_by", "$Customers(id:*)"},
{"include_fields", "id, $Customers(id :nest) as id"}
{"include_fields", "id, $Customers(id , strategy:nest) as id"}
};
search_op = collectionManager.do_search(req_params, embedded_params, json_res, now_ts);
ASSERT_FALSE(search_op.ok());
@ -3110,7 +3110,7 @@ TEST_F(CollectionJoinTest, IncludeExcludeFieldsByReference) {
{"query_by", "customer_name"},
{"filter_by", "product_price:<100"},
// With merge, alias is prepended
{"include_fields", "$Products(product_name:merge) as prod, product_price"}
{"include_fields", "$Products(product_name, strategy:merge) as prod, product_price"}
};
search_op = collectionManager.do_search(req_params, embedded_params, json_res, now_ts);
ASSERT_TRUE(search_op.ok());
@ -3130,7 +3130,7 @@ TEST_F(CollectionJoinTest, IncludeExcludeFieldsByReference) {
{"query_by", "customer_name"},
{"filter_by", "product_price:<100"},
// With nest, alias becomes the key
{"include_fields", "$Products(product_name:nest) as prod, product_price"}
{"include_fields", "$Products(product_name, strategy:nest) as prod, product_price"}
};
search_op = collectionManager.do_search(req_params, embedded_params, json_res, now_ts);
ASSERT_TRUE(search_op.ok());
@ -3151,7 +3151,7 @@ TEST_F(CollectionJoinTest, IncludeExcludeFieldsByReference) {
{"query_by", "product_name"},
{"filter_by", "$Customers(id:*)"},
// With nest, alias becomes the key
{"include_fields", "$Customers(customer_name, product_price :nest) as CustomerPrices, product_name"}
{"include_fields", "$Customers(customer_name, product_price , strategy:nest) as CustomerPrices, product_name"}
};
search_op = collectionManager.do_search(req_params, embedded_params, json_res, now_ts);
ASSERT_TRUE(search_op.ok());
@ -3374,7 +3374,7 @@ TEST_F(CollectionJoinTest, IncludeExcludeFieldsByReference) {
{"q", "R"},
{"query_by", "user_name"},
{"filter_by", "$Participants(org_id:=org_a) && $Links(repo_id:=repo_b)"},
{"include_fields", "user_id, user_name, $Repos(repo_content:merge), $Organizations(name:merge) as org"},
{"include_fields", "user_id, user_name, $Repos(repo_content, strategy:merge), $Organizations(name, strategy:merge) as org"},
{"exclude_fields", "$Participants(*), $Links(*), "}
};
search_op = collectionManager.do_search(req_params, embedded_params, json_res, now_ts);
@ -3448,7 +3448,7 @@ TEST_F(CollectionJoinTest, FilterByReferenceArrayField) {
std::map<std::string, std::string> req_params = {
{"collection", "songs"},
{"q", "*"},
{"include_fields", "$genres(name:merge) as genre"},
{"include_fields", "$genres(name, strategy:merge) as genre"},
{"exclude_fields", "genres_sequence_id"},
};
nlohmann::json embedded_params;
@ -3479,7 +3479,7 @@ TEST_F(CollectionJoinTest, FilterByReferenceArrayField) {
{"collection", "genres"},
{"q", "*"},
{"filter_by", "$songs(id: *)"},
{"include_fields", "$songs(title:merge) as song"},
{"include_fields", "$songs(title, strategy:merge) as song"},
};
search_op_bool = collectionManager.do_search(req_params, embedded_params, json_res, now_ts);
ASSERT_TRUE(search_op_bool.ok());
@ -3790,7 +3790,7 @@ TEST_F(CollectionJoinTest, FilterByObjectReferenceField) {
req_params = {
{"collection", "Foods"},
{"q", "*"},
{"include_fields", "$Portions(*:merge)"}
{"include_fields", "$Portions(*, strategy:merge)"}
};
search_op_bool = collectionManager.do_search(req_params, embedded_params, json_res, now_ts);
ASSERT_TRUE(search_op_bool.ok());
@ -3847,7 +3847,7 @@ TEST_F(CollectionJoinTest, FilterByObjectReferenceField) {
req_params = {
{"collection", "Foods"},
{"q", "*"},
{"include_fields", "$Portions(*:merge)"}
{"include_fields", "$Portions(*, strategy:merge)"}
};
search_op_bool = collectionManager.do_search(req_params, embedded_params, json_res, now_ts);
LOG(INFO) << search_op_bool.error();
@ -4221,7 +4221,7 @@ TEST_F(CollectionJoinTest, SortByReference) {
{"query_by", "product_name"},
{"filter_by", "$Customers(customer_id:=customer_a)"},
{"sort_by", "$Customers(product_price:asc)"},
{"include_fields", "product_id, $Customers(product_price:merge)"},
{"include_fields", "product_id, $Customers(product_price, strategy:merge)"},
};
search_op = collectionManager.do_search(req_params, embedded_params, json_res, now_ts);
ASSERT_TRUE(search_op.ok());
@ -4240,7 +4240,7 @@ TEST_F(CollectionJoinTest, SortByReference) {
{"query_by", "product_name"},
{"filter_by", "$Customers(customer_id:=customer_a)"},
{"sort_by", "$Customers(product_price:desc)"},
{"include_fields", "product_id, $Customers(product_price:merge)"},
{"include_fields", "product_id, $Customers(product_price, strategy:merge)"},
};
search_op = collectionManager.do_search(req_params, embedded_params, json_res, now_ts);
ASSERT_TRUE(search_op.ok());
@ -4260,7 +4260,7 @@ TEST_F(CollectionJoinTest, SortByReference) {
{"query_by", "product_name"},
{"filter_by", "$Customers(customer_id:=customer_a)"},
{"sort_by", "$Customers(product_id:asc)"},
{"include_fields", "product_id, $Customers(product_price:merge)"},
{"include_fields", "product_id, $Customers(product_price, strategy:merge)"},
};
search_op = collectionManager.do_search(req_params, embedded_params, json_res, now_ts);
ASSERT_TRUE(search_op.ok());
@ -4280,7 +4280,7 @@ TEST_F(CollectionJoinTest, SortByReference) {
{"query_by", "product_name"},
{"filter_by", "$Customers(customer_id:=customer_a)"},
{"sort_by", "$Customers(_eval(product_available:true):asc)"},
{"include_fields", "product_id, $Customers(product_price:merge)"},
{"include_fields", "product_id, $Customers(product_price, strategy:merge)"},
};
search_op = collectionManager.do_search(req_params, embedded_params, json_res, now_ts);
ASSERT_TRUE(search_op.ok());
@ -4299,7 +4299,7 @@ TEST_F(CollectionJoinTest, SortByReference) {
{"query_by", "product_name"},
{"filter_by", "$Customers(customer_id:=customer_a)"},
{"sort_by", "$Customers(_eval(product_available:true):desc)"},
{"include_fields", "product_id, $Customers(product_price:merge)"},
{"include_fields", "product_id, $Customers(product_price, strategy:merge)"},
};
search_op = collectionManager.do_search(req_params, embedded_params, json_res, now_ts);
ASSERT_TRUE(search_op.ok());
@ -4319,7 +4319,7 @@ TEST_F(CollectionJoinTest, SortByReference) {
{"query_by", "product_name"},
{"filter_by", "$Customers(customer_id:=customer_a)"},
{"sort_by", "$Customers(product_price:desc)"},
{"include_fields", "product_id, $Customers(product_price:merge)"},
{"include_fields", "product_id, $Customers(product_price, strategy:merge)"},
};
search_op = collectionManager.do_search(req_params, embedded_params, json_res, now_ts);
ASSERT_TRUE(search_op.ok());
@ -4338,7 +4338,7 @@ TEST_F(CollectionJoinTest, SortByReference) {
{"q", R"("our")"},
{"query_by", "product_description"},
{"filter_by", "$Customers(customer_id:=customer_a)"},
{"include_fields", "product_id, $Customers(product_price:merge)"},
{"include_fields", "product_id, $Customers(product_price, strategy:merge)"},
{"sort_by", "$Customers(product_price:desc)"},
};
search_op = collectionManager.do_search(req_params, embedded_params, json_res, now_ts);
@ -4358,7 +4358,7 @@ TEST_F(CollectionJoinTest, SortByReference) {
{"q", "natural products"},
{"query_by", "embedding"},
{"filter_by", "$Customers(customer_id:=customer_a)"},
{"include_fields", "product_id, $Customers(product_price:merge)"},
{"include_fields", "product_id, $Customers(product_price, strategy:merge)"},
{"sort_by", "$Customers(product_price:desc)"},
};
search_op = collectionManager.do_search(req_params, embedded_params, json_res, now_ts);
@ -4392,7 +4392,7 @@ TEST_F(CollectionJoinTest, SortByReference) {
{"q", "*"},
{"vector_query", "embedding:(" + vec_string + ", flat_search_cutoff: 0)"},
{"filter_by", "$Customers(customer_id:=customer_a)"},
{"include_fields", "product_id, $Customers(product_price:merge)"},
{"include_fields", "product_id, $Customers(product_price, strategy:merge)"},
{"sort_by", "$Customers(product_price:desc)"},
};
search_op = collectionManager.do_search(req_params, embedded_params, json_res, now_ts);
@ -4416,7 +4416,7 @@ TEST_F(CollectionJoinTest, SortByReference) {
{"q", "soap"},
{"query_by", "product_name, embedding"},
{"filter_by", "$Customers(customer_id:=customer_a)"},
{"include_fields", "product_id, $Customers(product_price:merge)"},
{"include_fields", "product_id, $Customers(product_price, strategy:merge)"},
{"sort_by", "$Customers(product_price:desc)"},
};
search_op = collectionManager.do_search(req_params, embedded_params, json_res, now_ts);
@ -4442,7 +4442,7 @@ TEST_F(CollectionJoinTest, SortByReference) {
{"q", "natural products"},
{"query_by", "product_name, embedding"},
{"filter_by", "$Customers(customer_id:=customer_a)"},
{"include_fields", "product_id, $Customers(product_price:merge)"},
{"include_fields", "product_id, $Customers(product_price, strategy:merge)"},
{"sort_by", "$Customers(product_price:desc)"},
};
search_op = collectionManager.do_search(req_params, embedded_params, json_res, now_ts);
@ -4467,7 +4467,7 @@ TEST_F(CollectionJoinTest, SortByReference) {
{"query_by", "product_name"},
{"infix", "always"},
{"filter_by", "$Customers(customer_id:=customer_a)"},
{"include_fields", "product_id, $Customers(product_price:merge)"},
{"include_fields", "product_id, $Customers(product_price, strategy:merge)"},
{"sort_by", "$Customers(product_price:desc)"},
};
search_op = collectionManager.do_search(req_params, embedded_params, json_res, now_ts);
@ -4486,7 +4486,7 @@ TEST_F(CollectionJoinTest, SortByReference) {
{"collection", "Customers"},
{"q", "*"},
{"filter_by", "customer_name:= [Joe, Dan] && product_price:<100"},
{"include_fields", "$Products(product_name:merge), product_price"},
{"include_fields", "$Products(product_name, strategy:merge), product_price"},
{"sort_by", "$Products(product_name:desc)"},
};
search_op = collectionManager.do_search(req_params, embedded_params, json_res, now_ts);
@ -4505,7 +4505,7 @@ TEST_F(CollectionJoinTest, SortByReference) {
{"collection", "Customers"},
{"q", "*"},
{"filter_by", "customer_name:= [Joe, Dan] && product_price:<100"},
{"include_fields", "$Products(product_name:merge), product_price"},
{"include_fields", "$Products(product_name, strategy:merge), product_price"},
{"sort_by", "$Products(product_name:asc)"},
};
search_op = collectionManager.do_search(req_params, embedded_params, json_res, now_ts);
@ -4523,7 +4523,7 @@ TEST_F(CollectionJoinTest, SortByReference) {
req_params = {
{"collection", "Customers"},
{"q", "*"},
{"include_fields", "$Products(product_name:merge), customer_name, id"},
{"include_fields", "$Products(product_name, strategy:merge), customer_name, id"},
{"sort_by", "$Products(product_name:asc), customer_name:desc"},
};
search_op = collectionManager.do_search(req_params, embedded_params, json_res, now_ts);
@ -4696,7 +4696,7 @@ TEST_F(CollectionJoinTest, SortByReference) {
{"collection", "Users"},
{"q", "*"},
{"filter_by", "$Links(repo_id:=[repo_a, repo_d])"},
{"include_fields", "user_id, user_name, $Repos(repo_content, repo_stars:merge), "},
{"include_fields", "user_id, user_name, $Repos(repo_content, repo_stars, strategy:merge), "},
{"exclude_fields", "$Links(*), "},
{"sort_by", "$Repos(repo_stars: asc)"}
};
@ -4726,7 +4726,7 @@ TEST_F(CollectionJoinTest, SortByReference) {
{"collection", "Users"},
{"q", "*"},
{"filter_by", "$Links(repo_id:=[repo_a, repo_d])"},
{"include_fields", "user_id, user_name, $Repos(repo_content, repo_stars:merge), "},
{"include_fields", "user_id, user_name, $Repos(repo_content, repo_stars, strategy:merge), "},
{"exclude_fields", "$Links(*), "},
{"sort_by", "$Repos(repo_stars: desc), user_name:desc"}
};
@ -5089,7 +5089,7 @@ TEST_F(CollectionJoinTest, FilterByReferenceAlias) {
{"collection", "Customers"},
{"q", "*"},
{"filter_by", "customer_name:= [Joe, Dan] && product_price:<100"},
{"include_fields", "$Products_alias(product_name:merge), product_price"},
{"include_fields", "$Products_alias(product_name, strategy:merge), product_price"},
{"sort_by", "$Products_alias(product_name:desc)"},
};
search_op = collectionManager.do_search(req_params, embedded_params, json_res, now_ts);

View File

@ -1541,16 +1541,23 @@ TEST_F(CollectionManagerTest, InitializeRefIncludeExcludeFields) {
exclude_fields_vec.clear();
filter_query = "";
include_fields_vec = {"$Customers(product_price: foo) as customers"};
include_fields_vec = {"$Customers(product_price, strategy: foo) as customers"};
initialize_op = CollectionManager::_initialize_ref_include_exclude_fields_vec(filter_query, include_fields_vec,
exclude_fields_vec,
ref_include_exclude_fields_vec);
ASSERT_FALSE(initialize_op.ok());
ASSERT_EQ("Error parsing `$Customers(product_price: foo) as customers`: Unknown include strategy `foo`. "
ASSERT_EQ("Error parsing `$Customers(product_price, strategy: foo) as customers`: Unknown include strategy `foo`. "
"Valid options are `merge`, `nest`, `nest_array`.", initialize_op.error());
include_fields_vec = {"$Customers(product_price, foo: bar) as customers"};
initialize_op = CollectionManager::_initialize_ref_include_exclude_fields_vec(filter_query, include_fields_vec,
exclude_fields_vec,
ref_include_exclude_fields_vec);
ASSERT_FALSE(initialize_op.ok());
ASSERT_EQ("Unknown reference `include_fields` parameter: `foo`.", initialize_op.error());
filter_query = "$Customers(customer_id:=customer_a && (product_price:>100 && product_price:<200))";
include_fields_vec = {"$Customers(product_price: merge) as customers"};
include_fields_vec = {"$Customers(product_price, strategy: merge) as customers"};
initialize_op = CollectionManager::_initialize_ref_include_exclude_fields_vec(filter_query, include_fields_vec,
exclude_fields_vec,
ref_include_exclude_fields_vec);
@ -1564,7 +1571,7 @@ TEST_F(CollectionManagerTest, InitializeRefIncludeExcludeFields) {
ref_include_exclude_fields_vec.clear();
filter_query = "$Customers(customer_id:=customer_a && (product_price:>100 && product_price:<200))";
include_fields_vec = {"$Customers(product_price: nest_array) as customers"};
include_fields_vec = {"$Customers(product_price, strategy: nest_array) as customers"};
initialize_op = CollectionManager::_initialize_ref_include_exclude_fields_vec(filter_query, include_fields_vec,
exclude_fields_vec,
ref_include_exclude_fields_vec);
@ -1603,14 +1610,14 @@ TEST_F(CollectionManagerTest, InitializeRefIncludeExcludeFields) {
ref_include_exclude_fields_vec.clear();
filter_query = "$product_variants( $inventory($retailers(location:(33.865,-118.375,100 km))))";
include_fields_vec = {"$product_variants(title, $inventory(qty:merge) as inventory: nest) as variants"};
include_fields_vec = {"$product_variants(title, $inventory(qty, strategy:merge) as inventory, strategy: nest) as variants"};
initialize_op = CollectionManager::_initialize_ref_include_exclude_fields_vec(filter_query, include_fields_vec,
exclude_fields_vec,
ref_include_exclude_fields_vec);
ASSERT_TRUE(initialize_op.ok());
ASSERT_EQ(1, ref_include_exclude_fields_vec.size());
ASSERT_EQ("product_variants", ref_include_exclude_fields_vec[0].collection_name);
ASSERT_EQ("title,", ref_include_exclude_fields_vec[0].include_fields);
ASSERT_EQ("title", ref_include_exclude_fields_vec[0].include_fields);
ASSERT_EQ("variants", ref_include_exclude_fields_vec[0].alias);
ASSERT_EQ(ref_include::nest, ref_include_exclude_fields_vec[0].strategy);
@ -1628,15 +1635,15 @@ TEST_F(CollectionManagerTest, InitializeRefIncludeExcludeFields) {
ref_include_exclude_fields_vec.clear();
filter_query = "$product_variants( $inventory(id:*) && $retailers(location:(33.865,-118.375,100 km)))";
include_fields_vec = {"$product_variants(title, $inventory(qty:merge) as inventory,"
" $retailers(title): merge) as variants"};
include_fields_vec = {"$product_variants(title, $inventory(qty, strategy:merge) as inventory,"
" $retailers(title), strategy: merge) as variants"};
initialize_op = CollectionManager::_initialize_ref_include_exclude_fields_vec(filter_query, include_fields_vec,
exclude_fields_vec,
ref_include_exclude_fields_vec);
ASSERT_TRUE(initialize_op.ok());
ASSERT_EQ(1, ref_include_exclude_fields_vec.size());
ASSERT_EQ("product_variants", ref_include_exclude_fields_vec[0].collection_name);
ASSERT_EQ("title,", ref_include_exclude_fields_vec[0].include_fields);
ASSERT_EQ("title", ref_include_exclude_fields_vec[0].include_fields);
ASSERT_EQ("variants.", ref_include_exclude_fields_vec[0].alias);
ASSERT_EQ(ref_include::merge, ref_include_exclude_fields_vec[0].strategy);
@ -1653,8 +1660,8 @@ TEST_F(CollectionManagerTest, InitializeRefIncludeExcludeFields) {
ref_include_exclude_fields_vec.clear();
filter_query = "$product_variants( $inventory(id:*) && $retailers(location:(33.865,-118.375,100 km)))";
include_fields_vec = {"$product_variants(title, $inventory(qty:merge) as inventory, description,"
" $retailers(title), foo: merge) as variants"};
include_fields_vec = {"$product_variants(title, $inventory(qty, strategy:merge) as inventory, description,"
" $retailers(title), foo, strategy: merge) as variants"};
initialize_op = CollectionManager::_initialize_ref_include_exclude_fields_vec(filter_query, include_fields_vec,
exclude_fields_vec,
ref_include_exclude_fields_vec);
@ -1722,7 +1729,7 @@ TEST_F(CollectionManagerTest, InitializeRefIncludeExcludeFields) {
ref_include_exclude_fields_vec.clear();
filter_query = "$product_variants( $inventory($retailers(location:(33.865,-118.375,100 km))))";
include_fields_vec = {"$product_variants(title, $inventory(qty:merge) as inventory: nest) as variants"};
include_fields_vec = {"$product_variants(title, $inventory(qty, strategy:merge) as inventory, strategy: nest) as variants"};
exclude_fields_vec = {"$product_variants(title, $inventory(qty, $retailers(title)))"};
initialize_op = CollectionManager::_initialize_ref_include_exclude_fields_vec(filter_query, include_fields_vec,
exclude_fields_vec,
@ -1730,7 +1737,7 @@ TEST_F(CollectionManagerTest, InitializeRefIncludeExcludeFields) {
ASSERT_TRUE(initialize_op.ok());
ASSERT_EQ(1, ref_include_exclude_fields_vec.size());
ASSERT_EQ("product_variants", ref_include_exclude_fields_vec[0].collection_name);
ASSERT_EQ("title,", ref_include_exclude_fields_vec[0].include_fields);
ASSERT_EQ("title", ref_include_exclude_fields_vec[0].include_fields);
ASSERT_EQ("title,", ref_include_exclude_fields_vec[0].exclude_fields);
ASSERT_EQ("variants", ref_include_exclude_fields_vec[0].alias);
ASSERT_EQ(ref_include::nest, ref_include_exclude_fields_vec[0].strategy);

View File

@ -450,18 +450,18 @@ TEST(StringUtilsTest, SplitIncludeExcludeFields) {
}
TEST(StringUtilsTest, SplitReferenceIncludeExcludeFields) {
std::string include_fields = "$retailer(id,title: merge) as retailer_info:merge) as variants, foo", token;
std::string include_fields = "$retailer(id,title,strategy:merge) as retailer_info, strategy:merge) as variants, foo", token;
size_t index = 0;
auto tokenize_op = StringUtils::split_reference_include_exclude_fields(include_fields, index, token);
ASSERT_TRUE(tokenize_op.ok());
ASSERT_EQ("$retailer(id,title: merge) as retailer_info", token);
ASSERT_EQ(":merge) as variants, foo", include_fields.substr(index));
ASSERT_EQ("$retailer(id,title,strategy:merge) as retailer_info", token);
ASSERT_EQ(", strategy:merge) as variants, foo", include_fields.substr(index));
include_fields = "$inventory(qty,sku,$retailer(id,title: merge) as retailer_info) as inventory) as variants, foo";
include_fields = "$inventory(qty,sku,$retailer(id,title, strategy : merge) as retailer_info) as inventory) as variants, foo";
index = 0;
tokenize_op = StringUtils::split_reference_include_exclude_fields(include_fields, index, token);
ASSERT_TRUE(tokenize_op.ok());
ASSERT_EQ("$inventory(qty,sku,$retailer(id,title: merge) as retailer_info) as inventory", token);
ASSERT_EQ("$inventory(qty,sku,$retailer(id,title, strategy : merge) as retailer_info) as inventory", token);
ASSERT_EQ(") as variants, foo", include_fields.substr(index));
std::string exclude_fields = "$Collection(title), $product_variants(id,$inventory(qty,sku,$retailer(id,title)))";