mirror of
https://github.com/typesense/typesense.git
synced 2025-05-21 06:02:26 +08:00
adding sort by alpha
This commit is contained in:
parent
e70e8d070a
commit
cfcac97fdc
@ -72,7 +72,7 @@ private:
|
||||
};
|
||||
|
||||
struct facet_doc_ids_list_t {
|
||||
tsl::htrie_map<char, facet_id_seq_ids_t> fvalue_seq_ids;
|
||||
std::map<std::string, facet_id_seq_ids_t> fvalue_seq_ids;
|
||||
std::list<facet_count_t> counts;
|
||||
posting_list_t* seq_id_hashes = nullptr;
|
||||
|
||||
@ -89,8 +89,8 @@ private:
|
||||
|
||||
~facet_doc_ids_list_t() {
|
||||
for(auto it = fvalue_seq_ids.begin(); it != fvalue_seq_ids.end(); ++it) {
|
||||
if(it.value().seq_ids) {
|
||||
ids_t::destroy_list(it.value().seq_ids);
|
||||
if(it->second.seq_ids) {
|
||||
ids_t::destroy_list(it->second.seq_ids);
|
||||
}
|
||||
}
|
||||
|
||||
@ -113,8 +113,8 @@ public:
|
||||
|
||||
~facet_index_t();
|
||||
|
||||
void insert(const std::string& field_name, bool is_string,
|
||||
std::unordered_map<facet_value_id_t, std::vector<uint32_t>, facet_value_id_t::Hash>& fvalue_to_seq_ids,
|
||||
void insert(const std::string& field_name, std::unordered_map<facet_value_id_t,
|
||||
std::vector<uint32_t>, facet_value_id_t::Hash>& fvalue_to_seq_ids,
|
||||
std::unordered_map<uint32_t, std::vector<facet_value_id_t>>& seq_id_to_fvalues);
|
||||
|
||||
void erase(const std::string& field_name);
|
||||
@ -127,7 +127,7 @@ public:
|
||||
|
||||
size_t intersect(const std::string& val, const uint32_t* result_ids, size_t result_id_len,
|
||||
size_t max_facet_count, std::map<std::string, uint32_t>& found,
|
||||
bool is_wildcard_no_filter_query);
|
||||
bool is_wildcard_no_filter_query, const std::string& sort_order = "");
|
||||
|
||||
size_t get_facet_indexes(const std::string& field,
|
||||
std::map<uint32_t, std::vector<uint32_t>>& seqid_countIndexes);
|
||||
|
@ -377,8 +377,7 @@ private:
|
||||
size_t group_limit, const std::vector<std::string>& group_by_fields,
|
||||
const uint32_t* result_ids, size_t results_size,
|
||||
int max_facet_count, bool is_wildcard_query, bool no_filters_provided,
|
||||
facet_index_type_t facet_index_type
|
||||
) const;
|
||||
facet_index_type_t facet_index_type, const facet_sort_by& facet_sort_params={}) const;
|
||||
|
||||
bool static_filter_query_eval(const override_t* override, std::vector<std::string>& tokens,
|
||||
filter_node_t*& filter_tree_root) const;
|
||||
@ -633,7 +632,7 @@ public:
|
||||
// Public operations
|
||||
|
||||
Option<bool> run_search(search_args* search_params, const std::string& collection_name,
|
||||
facet_index_type_t facet_index_type);
|
||||
facet_index_type_t facet_index_type, const facet_sort_by& facet_sort_params={});
|
||||
|
||||
Option<bool> search(std::vector<query_tokens_t>& field_query_tokens, const std::vector<search_field_t>& the_fields,
|
||||
const text_match_type_t match_type,
|
||||
@ -658,7 +657,8 @@ public:
|
||||
const size_t max_extra_suffix, const size_t facet_query_num_typos,
|
||||
const bool filter_curated_hits, enable_t split_join_tokens,
|
||||
const vector_query_t& vector_query, size_t facet_sample_percent, size_t facet_sample_threshold,
|
||||
const std::string& collection_name, facet_index_type_t facet_index_type = DETECT) const;
|
||||
const std::string& collection_name, facet_index_type_t facet_index_type = DETECT,
|
||||
const facet_sort_by& facet_sort_params={}) const;
|
||||
|
||||
void remove_field(uint32_t seq_id, const nlohmann::json& document, const std::string& field_name);
|
||||
|
||||
|
@ -1631,7 +1631,7 @@ Option<nlohmann::json> Collection::search(std::string raw_query,
|
||||
|
||||
std::unique_ptr<search_args> search_params_guard(search_params);
|
||||
|
||||
auto search_op = index->run_search(search_params, name, facet_index_type);
|
||||
auto search_op = index->run_search(search_params, name, facet_index_type, facet_sort_param);
|
||||
|
||||
// filter_tree_root might be updated in Index::static_filter_query_eval.
|
||||
filter_tree_root_guard.release();
|
||||
@ -2114,7 +2114,7 @@ Option<nlohmann::json> Collection::search(std::string raw_query,
|
||||
}
|
||||
|
||||
std::unordered_map<std::string, size_t> ftoken_pos;
|
||||
std::vector<string>& ftokens = a_facet.hash_tokens[kv.first];
|
||||
std::vector<std::string>& ftokens = a_facet.hash_tokens[kv.first];
|
||||
//LOG(INFO) << "working on hash_tokens for hash " << kv.first << " with size " << ftokens.size();
|
||||
for(size_t ti = 0; ti < ftokens.size(); ti++) {
|
||||
if(the_field.is_bool()) {
|
||||
@ -2187,9 +2187,19 @@ Option<nlohmann::json> Collection::search(std::string raw_query,
|
||||
}
|
||||
}
|
||||
|
||||
if(!facet_sort_param.param.empty()) {
|
||||
if(facet_sort_param.param == "alpha") {
|
||||
bool is_asc = facet_sort_param.order == "asc";
|
||||
std::stable_sort(facet_values.begin(), facet_values.end(), [&](const auto& fv1, const auto& fv2) {
|
||||
std::stable_sort(facet_values.begin(), facet_values.end(),
|
||||
[&](const auto& fv1, const auto& fv2) {
|
||||
if(is_asc) {
|
||||
return fv1.value < fv2.value;
|
||||
}
|
||||
return fv1.value > fv2.value;
|
||||
});
|
||||
} else if(!facet_sort_param.param.empty()) {
|
||||
bool is_asc = facet_sort_param.order == "asc";
|
||||
std::stable_sort(facet_values.begin(), facet_values.end(),
|
||||
[&](const auto& fv1, const auto& fv2) {
|
||||
if(is_asc) {
|
||||
return fv1.sort_field_val < fv2.sort_field_val;
|
||||
}
|
||||
@ -2199,7 +2209,6 @@ Option<nlohmann::json> Collection::search(std::string raw_query,
|
||||
if(facet_values.size() > max_facet_values) {
|
||||
facet_values.erase(facet_values.begin() + max_facet_values, facet_values.end());
|
||||
}
|
||||
|
||||
} else {
|
||||
std::stable_sort(facet_values.begin(), facet_values.end(), Collection::facet_count_str_compare);
|
||||
}
|
||||
@ -5006,20 +5015,24 @@ Option<bool> Collection::parse_facet(const std::string& facet_field, std::vector
|
||||
}
|
||||
|
||||
Option<bool> Collection::validate_facet_sort_by_field(const facet_sort_by& facet_sort_params) const {
|
||||
if (search_schema.count(facet_sort_params.param) == 0) {
|
||||
std::string error = "Could not find a facet field named `" + facet_sort_params.param + "` in the schema.";
|
||||
return Option<bool>(404, error);
|
||||
}
|
||||
if(facet_sort_params.param == "alpha") {
|
||||
//sort param can be either alphabetical sort or sort by other field
|
||||
} else {
|
||||
if (search_schema.count(facet_sort_params.param) == 0) {
|
||||
std::string error = "Could not find a facet field named `" + facet_sort_params.param + "` in the schema.";
|
||||
return Option<bool>(404, error);
|
||||
}
|
||||
|
||||
const field &a_field = search_schema.at(facet_sort_params.param);
|
||||
if (!a_field.nested) {
|
||||
std::string error = "Field for `facet_sort_by` should be nested from same facet field";
|
||||
return Option<bool>(400, error);
|
||||
}
|
||||
const field &a_field = search_schema.at(facet_sort_params.param);
|
||||
if (!a_field.nested) {
|
||||
std::string error = "Field for `facet_sort_by` should be nested from same facet field";
|
||||
return Option<bool>(400, error);
|
||||
}
|
||||
|
||||
if(a_field.is_string()) {
|
||||
std::string error = "Field for `facet_sort_by` should not be string";
|
||||
return Option<bool>(400, error);
|
||||
if (a_field.is_string()) {
|
||||
std::string error = "Field for `facet_sort_by` should not be string";
|
||||
return Option<bool>(400, error);
|
||||
}
|
||||
}
|
||||
|
||||
if ((facet_sort_params.order != "asc") && (facet_sort_params.order != "desc")) {
|
||||
|
@ -11,8 +11,8 @@ void facet_index_t::initialize(const std::string& field) {
|
||||
}
|
||||
}
|
||||
|
||||
void facet_index_t::insert(const std::string& field_name, bool is_string,
|
||||
std::unordered_map<facet_value_id_t, std::vector<uint32_t>, facet_value_id_t::Hash>& fvalue_to_seq_ids,
|
||||
void facet_index_t::insert(const std::string& field_name,std::unordered_map<facet_value_id_t,
|
||||
std::vector<uint32_t>, facet_value_id_t::Hash>& fvalue_to_seq_ids,
|
||||
std::unordered_map<uint32_t, std::vector<facet_value_id_t>>& seq_id_to_fvalues) {
|
||||
|
||||
const auto facet_field_map_it = facet_field_map.find(field_name);
|
||||
@ -21,7 +21,7 @@ void facet_index_t::insert(const std::string& field_name, bool is_string,
|
||||
}
|
||||
|
||||
auto& facet_index = facet_field_map_it->second;
|
||||
tsl::htrie_map<char, facet_id_seq_ids_t>& fvalue_index = facet_index.fvalue_seq_ids;
|
||||
auto& fvalue_index = facet_index.fvalue_seq_ids;
|
||||
auto fhash_index = facet_index.seq_id_hashes;
|
||||
|
||||
for(const auto& seq_id_fvalues: seq_id_to_fvalues) {
|
||||
@ -35,7 +35,7 @@ void facet_index_t::insert(const std::string& field_name, bool is_string,
|
||||
|
||||
if(fvalue.facet_id == UINT32_MAX) {
|
||||
// float, int32 & bool will provide facet_id as their own numerical values
|
||||
facet_id = (fvalue_index_it == fvalue_index.end()) ? ++next_facet_id : fvalue_index_it->facet_id;
|
||||
facet_id = (fvalue_index_it == fvalue_index.end()) ? ++next_facet_id : fvalue_index_it->second.facet_id;
|
||||
}
|
||||
|
||||
real_facet_ids.push_back(facet_id);
|
||||
@ -61,13 +61,13 @@ void facet_index_t::insert(const std::string& field_name, bool is_string,
|
||||
fvalue_index.emplace(fvalue.facet_value, fis);
|
||||
} else if(facet_index.has_value_index) {
|
||||
for(const auto id : seq_ids) {
|
||||
ids_t::upsert(fvalue_index_it->seq_ids, id);
|
||||
ids_t::upsert(fvalue_index_it->second.seq_ids, id);
|
||||
}
|
||||
|
||||
auto facet_count_it = fvalue_index_it->facet_count_it;
|
||||
auto facet_count_it = fvalue_index_it->second.facet_count_it;
|
||||
|
||||
if(facet_count_it->facet_id == facet_id) {
|
||||
facet_count_it->count = ids_t::num_ids(fvalue_index_it->seq_ids);
|
||||
facet_count_it->count = ids_t::num_ids(fvalue_index_it->second.seq_ids);
|
||||
auto curr = facet_count_it;
|
||||
while (curr != count_list.begin() && std::prev(curr)->count < curr->count) {
|
||||
count_list.splice(curr, count_list, std::prev(curr)); // swaps list nodes
|
||||
@ -107,20 +107,22 @@ void facet_index_t::remove(const std::string& field_name, const uint32_t seq_id)
|
||||
std::vector<std::string> dead_fvalues;
|
||||
|
||||
for(auto facet_ids_seq_ids = facet_index_map.begin(); facet_ids_seq_ids != facet_index_map.end(); facet_ids_seq_ids++) {
|
||||
void*& ids = facet_ids_seq_ids.value().seq_ids;
|
||||
void*& ids = facet_ids_seq_ids->second.seq_ids;
|
||||
if(ids && ids_t::contains(ids, seq_id)) {
|
||||
ids_t::erase(ids, seq_id);
|
||||
auto& count_list = facet_field_it->second.counts;
|
||||
auto key = facet_ids_seq_ids.key();
|
||||
auto& facet_id_seq_ids = facet_ids_seq_ids.value();
|
||||
facet_ids_seq_ids.value().facet_count_it->count--;
|
||||
auto key = facet_ids_seq_ids->first;
|
||||
auto& facet_id_seq_ids = facet_ids_seq_ids->second;
|
||||
facet_ids_seq_ids->second.facet_count_it->count--;
|
||||
|
||||
if(ids_t::num_ids(ids) == 0) {
|
||||
ids_t::destroy_list(ids);
|
||||
std::string dead_fvalue;
|
||||
facet_ids_seq_ids.key(dead_fvalue);
|
||||
dead_fvalues.push_back(dead_fvalue);
|
||||
count_list.erase(facet_ids_seq_ids.value().facet_count_it);
|
||||
count_list.erase(facet_ids_seq_ids->second.facet_count_it);
|
||||
auto node = facet_index_map.extract(facet_ids_seq_ids->first);
|
||||
node.key() = dead_fvalue;
|
||||
facet_index_map.insert(std::move(node));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -147,7 +149,7 @@ size_t facet_index_t::get_facet_count(const std::string& field_name) {
|
||||
//returns the count of matching seq_ids from result array
|
||||
size_t facet_index_t::intersect(const std::string& field, const uint32_t* result_ids, size_t result_ids_len,
|
||||
size_t max_facet_count, std::map<std::string, uint32_t>& found,
|
||||
bool is_wildcard_no_filter_query) {
|
||||
bool is_wildcard_no_filter_query, const std::string& sort_order) {
|
||||
//LOG (INFO) << "intersecting field " << field;
|
||||
|
||||
const auto& facet_field_it = facet_field_map.find(field);
|
||||
@ -165,27 +167,55 @@ size_t facet_index_t::intersect(const std::string& field, const uint32_t* result
|
||||
size_t max_facets = is_wildcard_no_filter_query ? std::min((size_t)max_facet_count, counter_list.size()) :
|
||||
std::min((size_t)2 * max_facet_count, counter_list.size());
|
||||
|
||||
for(const auto& facet_count : counter_list) {
|
||||
//LOG(INFO) << "checking ids in facet_value " << facet_count.facet_value << " having total count "
|
||||
// << facet_count.count << ", is_wildcard_no_filter_query: " << is_wildcard_no_filter_query;
|
||||
auto intersect_fn = [&] (std::list<facet_count_t>::const_iterator facet_count_it) {
|
||||
uint32_t count = 0;
|
||||
|
||||
if(is_wildcard_no_filter_query) {
|
||||
count = facet_count.count;
|
||||
if (is_wildcard_no_filter_query) {
|
||||
count = facet_count_it->count;
|
||||
} else {
|
||||
auto ids = facet_index_map.at(facet_count.facet_value).seq_ids;
|
||||
if(!ids) {
|
||||
continue;
|
||||
auto ids = facet_index_map.at(facet_count_it->facet_value).seq_ids;
|
||||
if (!ids) {
|
||||
return;
|
||||
}
|
||||
count = ids_t::intersect_count(ids, result_ids, result_ids_len);
|
||||
}
|
||||
|
||||
if(count) {
|
||||
found[facet_count.facet_value] = count;
|
||||
if(found.size() == max_facets) {
|
||||
if (count) {
|
||||
found[facet_count_it->facet_value] = count;
|
||||
}
|
||||
};
|
||||
|
||||
if(sort_order.empty()) {
|
||||
for (auto facet_count_it = counter_list.begin(); facet_count_it != counter_list.end();
|
||||
++facet_count_it) {
|
||||
//LOG(INFO) << "checking ids in facet_value " << facet_count.facet_value << " having total count "
|
||||
// << facet_count.count << ", is_wildcard_no_filter_query: " << is_wildcard_no_filter_query;
|
||||
|
||||
intersect_fn(facet_count_it);
|
||||
if (found.size() == max_facets) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if(sort_order == "asc") {
|
||||
for(auto facet_index_map_it = facet_index_map.begin();
|
||||
facet_index_map_it != facet_index_map.end(); ++facet_index_map_it) {
|
||||
|
||||
intersect_fn(facet_index_map_it->second.facet_count_it);
|
||||
if (found.size() == max_facets) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if(sort_order == "desc") {
|
||||
for(auto facet_index_map_it = facet_index_map.rbegin();
|
||||
facet_index_map_it != facet_index_map.rend(); ++facet_index_map_it) {
|
||||
|
||||
intersect_fn(facet_index_map_it->second.facet_count_it);
|
||||
if (found.size() == max_facets) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return found.size();
|
||||
@ -209,12 +239,14 @@ size_t facet_index_t::get_facet_indexes(const std::string& field_name,
|
||||
std::vector<uint32_t> id_list;
|
||||
|
||||
for(auto facet_index_map_it = facet_index_map.begin(); facet_index_map_it != facet_index_map.end(); ++facet_index_map_it) {
|
||||
auto ids = facet_index_map_it->seq_ids;
|
||||
//auto ids = facet_index_map_it->seq_ids;
|
||||
auto ids = facet_index_map_it->second.seq_ids;
|
||||
ids_t::uncompress(ids, id_list);
|
||||
|
||||
// emplacing seq_id => next_facet_id
|
||||
for(const auto& id : id_list) {
|
||||
seqid_countIndexes[id].emplace_back(facet_index_map_it->facet_id);
|
||||
//seqid_countIndexes[id].emplace_back(facet_index_map_it->facet_id);
|
||||
seqid_countIndexes[id].emplace_back(facet_index_map_it->second.facet_id);
|
||||
}
|
||||
|
||||
id_list.clear();
|
||||
@ -253,7 +285,7 @@ void facet_index_t::handle_index_change(const std::string& field_name, size_t to
|
||||
// drop the value index for this field
|
||||
auto& fvalue_seq_ids = facet_index.fvalue_seq_ids;
|
||||
for(auto it = fvalue_seq_ids.begin(); it != fvalue_seq_ids.end(); ++it) {
|
||||
ids_t::destroy_list(it.value().seq_ids);
|
||||
ids_t::destroy_list(it->second.seq_ids);
|
||||
}
|
||||
fvalue_seq_ids.clear();
|
||||
facet_index.counts.clear();
|
||||
|
@ -770,7 +770,7 @@ void Index::index_field_in_memory(const field& afield, std::vector<index_record>
|
||||
}
|
||||
}
|
||||
|
||||
facet_index_v4->insert(afield.name, afield.is_string(), fvalue_to_seq_ids, seq_id_to_fvalues);
|
||||
facet_index_v4->insert(afield.name, fvalue_to_seq_ids, seq_id_to_fvalues);
|
||||
|
||||
auto tree_it = search_index.find(afield.faceted_name());
|
||||
if(tree_it == search_index.end()) {
|
||||
@ -1247,7 +1247,7 @@ void Index::do_facets(std::vector<facet> & facets, facet_query_t & facet_query,
|
||||
const size_t group_limit, const std::vector<std::string>& group_by_fields,
|
||||
const uint32_t* result_ids, size_t results_size,
|
||||
int max_facet_count, bool is_wildcard_query, bool no_filters_provided,
|
||||
facet_index_type_t facet_index_type) const {
|
||||
facet_index_type_t facet_index_type, const facet_sort_by& facet_sort_params) const {
|
||||
|
||||
if(results_size == 0) {
|
||||
return ;
|
||||
@ -1284,10 +1284,21 @@ void Index::do_facets(std::vector<facet> & facets, facet_query_t & facet_query,
|
||||
(results_size > 1000 && num_facet_values < 250) ||
|
||||
(results_size > 1000 && results_size * 2 > total_docs));
|
||||
|
||||
if(!facet_sort_params.param.empty() && facet_sort_params.param == "alpha") {
|
||||
std::map<std::string, uint32_t> facet_results;
|
||||
facet_index_v4->intersect(facet_field.name, result_ids, results_size, max_facet_count,
|
||||
facet_results, is_wildcard_no_filter_query, facet_sort_params.order);
|
||||
|
||||
for(const auto& kv : facet_results) {
|
||||
facet_count_t& facet_count = a_facet.result_map[kv.first];
|
||||
facet_count.count = kv.second;
|
||||
}
|
||||
a_facet.is_intersected = true;
|
||||
}
|
||||
#ifdef TEST_BUILD
|
||||
if(facet_index_type == VALUE) {
|
||||
else if(facet_index_type == VALUE) {
|
||||
#else
|
||||
if(facet_value_index_exists && use_value_index) {
|
||||
else if(facet_value_index_exists && use_value_index) {
|
||||
#endif
|
||||
// LOG(INFO) << "Using intersection to find facets";
|
||||
a_facet.is_intersected = true;
|
||||
@ -1742,7 +1753,7 @@ Option<bool> Index::do_reference_filtering_with_lock(filter_node_t* const filter
|
||||
}
|
||||
|
||||
Option<bool> Index::run_search(search_args* search_params, const std::string& collection_name,
|
||||
facet_index_type_t facet_index_type) {
|
||||
facet_index_type_t facet_index_type, const facet_sort_by& facet_sort_params) {
|
||||
return search(search_params->field_query_tokens,
|
||||
search_params->search_fields,
|
||||
search_params->match_type,
|
||||
@ -1778,7 +1789,8 @@ Option<bool> Index::run_search(search_args* search_params, const std::string& co
|
||||
search_params->facet_sample_percent,
|
||||
search_params->facet_sample_threshold,
|
||||
collection_name,
|
||||
facet_index_type);
|
||||
facet_index_type,
|
||||
facet_sort_params);
|
||||
}
|
||||
|
||||
void Index::collate_included_ids(const std::vector<token_t>& q_included_tokens,
|
||||
@ -2227,7 +2239,8 @@ Option<bool> Index::search(std::vector<query_tokens_t>& field_query_tokens, cons
|
||||
const bool filter_curated_hits, const enable_t split_join_tokens,
|
||||
const vector_query_t& vector_query,
|
||||
size_t facet_sample_percent, size_t facet_sample_threshold,
|
||||
const std::string& collection_name, facet_index_type_t facet_index_type) const {
|
||||
const std::string& collection_name, facet_index_type_t facet_index_type,
|
||||
const facet_sort_by& facet_sort_params) const {
|
||||
std::shared_lock lock(mutex);
|
||||
|
||||
auto filter_result_iterator = new filter_result_iterator_t(collection_name, this, filter_tree_root);
|
||||
@ -2848,7 +2861,7 @@ Option<bool> Index::search(std::vector<query_tokens_t>& field_query_tokens, cons
|
||||
batch_result_ids, batch_res_len, &facet_infos, max_facet_values,
|
||||
is_wildcard_query, no_filters_provided, estimate_facets, facet_sample_percent,
|
||||
&parent_search_begin, &parent_search_stop_ms, &parent_search_cutoff,
|
||||
&num_processed, &m_process, &cv_process, facet_index_type]() {
|
||||
&num_processed, &m_process, &cv_process, facet_index_type, facet_sort_params]() {
|
||||
search_begin_us = parent_search_begin;
|
||||
search_stop_us = parent_search_stop_ms;
|
||||
search_cutoff = parent_search_cutoff;
|
||||
@ -2859,7 +2872,7 @@ Option<bool> Index::search(std::vector<query_tokens_t>& field_query_tokens, cons
|
||||
facet_infos, group_limit, group_by_fields,
|
||||
batch_result_ids, batch_res_len, max_facet_values,
|
||||
is_wildcard_query, no_filters_provided,
|
||||
facet_index_type);
|
||||
facet_index_type, facet_sort_params);
|
||||
std::unique_lock<std::mutex> lock(m_process);
|
||||
num_processed++;
|
||||
parent_search_cutoff = parent_search_cutoff || search_cutoff;
|
||||
@ -2941,7 +2954,7 @@ Option<bool> Index::search(std::vector<query_tokens_t>& field_query_tokens, cons
|
||||
do_facets(facets, facet_query, estimate_facets, facet_sample_percent,
|
||||
facet_infos, group_limit, group_by_fields, &included_ids_vec[0],
|
||||
included_ids_vec.size(), max_facet_values, is_wildcard_query, no_filters_provided,
|
||||
facet_index_type);
|
||||
facet_index_type, facet_sort_params);
|
||||
|
||||
all_result_ids_len += curated_topster->size;
|
||||
|
||||
|
@ -1992,4 +1992,122 @@ TEST_F(CollectionFacetingTest, FacetSortByOtherFieldVal) {
|
||||
ASSERT_EQ("Toyota", results["facet_counts"][0]["counts"][1]["value"]);
|
||||
ASSERT_EQ("Tata", results["facet_counts"][0]["counts"][2]["value"]);
|
||||
ASSERT_EQ("Maruti", results["facet_counts"][0]["counts"][3]["value"]);
|
||||
}
|
||||
|
||||
TEST_F(CollectionFacetingTest, FacetSortByAlpha) {
|
||||
nlohmann::json schema = R"({
|
||||
"name": "coll1",
|
||||
"fields": [
|
||||
{"name": "phone", "type": "string", "optional": false, "facet": true },
|
||||
{"name": "brand", "type": "string", "optional": false, "facet": true }
|
||||
]
|
||||
})"_json;
|
||||
|
||||
auto op = collectionManager.create_collection(schema);
|
||||
ASSERT_TRUE(op.ok());
|
||||
Collection *coll1 = op.get();
|
||||
|
||||
nlohmann::json doc;
|
||||
|
||||
doc["phone"] = "Oneplus 11R";
|
||||
doc["brand"] = "Oneplus";
|
||||
auto add_op = coll1->add(doc.dump(), CREATE);
|
||||
ASSERT_TRUE(add_op.ok());
|
||||
|
||||
doc["phone"] = "Fusion Plus";
|
||||
doc["brand"] = "Moto";
|
||||
add_op = coll1->add(doc.dump(), CREATE);
|
||||
ASSERT_TRUE(add_op.ok());
|
||||
|
||||
doc["phone"] = "S22 Ultra";
|
||||
doc["brand"] = "Samsung";
|
||||
add_op = coll1->add(doc.dump(), CREATE);
|
||||
ASSERT_TRUE(add_op.ok());
|
||||
|
||||
doc["phone"] = "GT Master";
|
||||
doc["brand"] = "Realme";
|
||||
add_op = coll1->add(doc.dump(), CREATE);
|
||||
ASSERT_TRUE(add_op.ok());
|
||||
|
||||
doc["phone"] = "T2";
|
||||
doc["brand"] = "Vivo";
|
||||
add_op = coll1->add(doc.dump(), CREATE);
|
||||
ASSERT_TRUE(add_op.ok());
|
||||
|
||||
doc["phone"] = "Mi 6";
|
||||
doc["brand"] = "Xiaomi";
|
||||
add_op = coll1->add(doc.dump(), CREATE);
|
||||
ASSERT_TRUE(add_op.ok());
|
||||
|
||||
doc["phone"] = "Z6 Lite";
|
||||
doc["brand"] = "Iqoo";
|
||||
add_op = coll1->add(doc.dump(), CREATE);
|
||||
ASSERT_TRUE(add_op.ok());
|
||||
|
||||
//sort facets by phone in asc order
|
||||
facet_sort_by facet_sort_param{"alpha", "asc"};
|
||||
auto search_op = coll1->search("*", {}, "", {"phone"},
|
||||
{}, {2}, 10, 1, FREQUENCY, {true},
|
||||
1, spp::sparse_hash_set<std::string>(),
|
||||
spp::sparse_hash_set<std::string>(), 10, "",
|
||||
30, 4, "",
|
||||
Index::TYPO_TOKENS_THRESHOLD, "", "", {},
|
||||
3, "<mark>", "</mark>", {},
|
||||
UINT32_MAX, true, false, true,
|
||||
"", false, 6000 * 1000, 4, 7,
|
||||
fallback, 4, {off}, INT16_MAX, INT16_MAX,
|
||||
2, 2, false, "",
|
||||
true, 0, max_score, 100,
|
||||
0, 0, HASH, 30000,
|
||||
2, "", {}, facet_sort_param);
|
||||
|
||||
if (!search_op.ok()) {
|
||||
LOG(ERROR) << search_op.error();
|
||||
FAIL();
|
||||
}
|
||||
|
||||
auto results = search_op.get();
|
||||
ASSERT_EQ(1, results["facet_counts"].size());
|
||||
ASSERT_EQ(7, results["facet_counts"][0]["counts"].size());
|
||||
ASSERT_EQ("Fusion Plus", results["facet_counts"][0]["counts"][0]["value"]);
|
||||
ASSERT_EQ("GT Master", results["facet_counts"][0]["counts"][1]["value"]);
|
||||
ASSERT_EQ("Mi 6", results["facet_counts"][0]["counts"][2]["value"]);
|
||||
ASSERT_EQ("Oneplus 11R", results["facet_counts"][0]["counts"][3]["value"]);
|
||||
ASSERT_EQ("S22 Ultra", results["facet_counts"][0]["counts"][4]["value"]);
|
||||
ASSERT_EQ("T2", results["facet_counts"][0]["counts"][5]["value"]);
|
||||
ASSERT_EQ("Z6 Lite", results["facet_counts"][0]["counts"][6]["value"]);
|
||||
|
||||
//sort facets by brand in desc order
|
||||
facet_sort_param.param = "alpha";
|
||||
facet_sort_param.order = "desc";
|
||||
search_op = coll1->search("*", {}, "", {"brand"},
|
||||
{}, {2}, 10, 1, FREQUENCY, {true},
|
||||
1, spp::sparse_hash_set<std::string>(),
|
||||
spp::sparse_hash_set<std::string>(), 10, "",
|
||||
30, 4, "",
|
||||
Index::TYPO_TOKENS_THRESHOLD, "", "", {},
|
||||
3, "<mark>", "</mark>", {},
|
||||
UINT32_MAX, true, false, true,
|
||||
"", false, 6000 * 1000, 4, 7,
|
||||
fallback, 4, {off}, INT16_MAX, INT16_MAX,
|
||||
2, 2, false, "",
|
||||
true, 0, max_score, 100,
|
||||
0, 0, HASH, 30000,
|
||||
2, "", {}, facet_sort_param);
|
||||
|
||||
if (!search_op.ok()) {
|
||||
LOG(ERROR) << search_op.error();
|
||||
FAIL();
|
||||
}
|
||||
|
||||
results = search_op.get();
|
||||
ASSERT_EQ(1, results["facet_counts"].size());
|
||||
ASSERT_EQ(7, results["facet_counts"][0]["counts"].size());
|
||||
ASSERT_EQ("Xiaomi", results["facet_counts"][0]["counts"][0]["value"]);
|
||||
ASSERT_EQ("Vivo", results["facet_counts"][0]["counts"][1]["value"]);
|
||||
ASSERT_EQ("Samsung", results["facet_counts"][0]["counts"][2]["value"]);
|
||||
ASSERT_EQ("Realme", results["facet_counts"][0]["counts"][3]["value"]);
|
||||
ASSERT_EQ("Oneplus", results["facet_counts"][0]["counts"][4]["value"]);
|
||||
ASSERT_EQ("Moto", results["facet_counts"][0]["counts"][5]["value"]);
|
||||
ASSERT_EQ("Iqoo", results["facet_counts"][0]["counts"][6]["value"]);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user