Fix _eval parsing. #1089

This commit is contained in:
Harpreet Sangar 2023-08-29 10:21:39 +05:30
parent 4608b9407f
commit a3d976b535
2 changed files with 55 additions and 0 deletions

View File

@ -623,6 +623,45 @@ bool CollectionManager::parse_sort_by_str(std::string sort_by_str, std::vector<s
char prev_non_space_char = 'a';
for(size_t i=0; i < sort_by_str.size(); i++) {
if (sort_field_expr.empty() && sort_by_str.substr(i, 5) == sort_field_const::eval) {
// Optional filtering
auto open_paren_pos = sort_by_str.find('(', i);
if (open_paren_pos == std::string::npos) {
return false;
}
sort_field_expr = sort_field_const::eval + "(";
i = open_paren_pos;
int paren_count = 1;
while (++i < sort_by_str.size() && paren_count > 0) {
if (sort_by_str[i] == '(') {
paren_count++;
} else if (sort_by_str[i] == ')') {
paren_count--;
}
sort_field_expr += sort_by_str[i];
}
if (paren_count != 0 || i >= sort_by_str.size()) {
return false;
}
while (sort_by_str[i] != ':' && ++i < sort_by_str.size());
if (i >= sort_by_str.size()) {
return false;
}
std::string order_str;
while (++i < sort_by_str.size() && sort_by_str[i] != ',') {
order_str += sort_by_str[i];
}
StringUtils::trim(order_str);
StringUtils::toupper(order_str);
sort_fields.emplace_back(sort_field_expr, order_str);
sort_field_expr = "";
continue;
}
if(i == sort_by_str.size()-1 || (sort_by_str[i] == ',' && !isdigit(prev_non_space_char))) {
if(i == sort_by_str.size()-1) {
sort_field_expr += sort_by_str[i];

View File

@ -2135,6 +2135,22 @@ TEST_F(CollectionSortingTest, OptionalFilteringViaSortingSearch) {
results = coll1->search("title", {"title"}, "", {}, sort_fields, {2}, 10, 1, FREQUENCY, {true}, 10).get();
ASSERT_EQ(5, results["hits"].size());
std::map<std::string, std::string> req_params = {
{"collection", "coll1"},
{"q", "title"},
{"query_by", "title"},
{"sort_by", "_eval(brand:[nike, adidas] && points:0):desc, points:DESC"}
};
nlohmann::json embedded_params;
std::string json_res;
auto now_ts = std::chrono::duration_cast<std::chrono::microseconds>(
std::chrono::system_clock::now().time_since_epoch()).count();
auto search_op = collectionManager.do_search(req_params, embedded_params, json_res, now_ts);
ASSERT_TRUE(search_op.ok());
results = nlohmann::json::parse(json_res);
ASSERT_EQ(5, results["hits"].size());
expected_ids = {"0", "4", "3", "2", "1"};
for(size_t i = 0; i < expected_ids.size(); i++) {
ASSERT_EQ(expected_ids[i], results["hits"][i]["document"]["id"].get<std::string>());