From c712cc0ca72a331d290ea0764847127c4a3dc38b Mon Sep 17 00:00:00 2001 From: Kishore Nallan Date: Fri, 21 May 2021 19:01:39 +0530 Subject: [PATCH] Ensure floating point precision is correct when faceted. --- include/string_utils.h | 2 ++ src/collection.cpp | 4 ++-- src/index.cpp | 6 +++--- src/string_utils.cpp | 6 ++++++ test/collection_faceting_test.cpp | 36 +++++++++++++++++++++++++++++++ 5 files changed, 49 insertions(+), 5 deletions(-) diff --git a/include/string_utils.h b/include/string_utils.h index c1d7f201..552a2b6b 100644 --- a/include/string_utils.h +++ b/include/string_utils.h @@ -294,4 +294,6 @@ struct StringUtils { } static std::map parse_query_string(const std::string& query); + + static std::string float_to_str(float value); }; \ No newline at end of file diff --git a/src/collection.cpp b/src/collection.cpp index f72e17d7..2e443153 100644 --- a/src/collection.cpp +++ b/src/collection.cpp @@ -1370,11 +1370,11 @@ bool Collection::facet_value_to_string(const facet &a_facet, const facet_count_t value = std::to_string(raw_val); } else if(facet_schema.at(a_facet.field_name).type == field_types::FLOAT) { float raw_val = document[a_facet.field_name].get(); - value = std::to_string(raw_val); + value = StringUtils::float_to_str(raw_val); value.erase ( value.find_last_not_of('0') + 1, std::string::npos ); // remove trailing zeros } else if(facet_schema.at(a_facet.field_name).type == field_types::FLOAT_ARRAY) { float raw_val = document[a_facet.field_name][facet_count.array_pos].get(); - value = std::to_string(raw_val); + value = StringUtils::float_to_str(raw_val); value.erase ( value.find_last_not_of('0') + 1, std::string::npos ); // remove trailing zeros } else if(facet_schema.at(a_facet.field_name).type == field_types::BOOL) { value = std::to_string(document[a_facet.field_name].get()); diff --git a/src/index.cpp b/src/index.cpp index aa4908ab..bfeed79c 100644 --- a/src/index.cpp +++ b/src/index.cpp @@ -163,7 +163,7 @@ Option Index::index_in_memory(const nlohmann::json &document, uint32_t } } else if(field_pair.second.type == field_types::FLOAT_ARRAY) { for(float value: document[field_name]){ - strings.push_back(std::to_string(value)); + strings.push_back(StringUtils::float_to_str(value)); } } else if(field_pair.second.type == field_types::BOOL_ARRAY) { for(bool value: document[field_name]){ @@ -179,7 +179,7 @@ Option Index::index_in_memory(const nlohmann::json &document, uint32_t } else if(field_pair.second.type == field_types::INT64) { text = std::to_string(document[field_name].get()); } else if(field_pair.second.type == field_types::FLOAT) { - text = std::to_string(document[field_name].get()); + text = StringUtils::float_to_str(document[field_name].get()); } else if(field_pair.second.type == field_types::BOOL) { text = std::to_string(document[field_name].get()); } @@ -2608,7 +2608,7 @@ Option Index::coerce_string(const DIRTY_VALUES& dirty_values, const st } else if(item.is_number_float()) { - item = std::to_string((float)item); + item = StringUtils::float_to_str((float)item); } else if(item.is_boolean()) { diff --git a/src/string_utils.cpp b/src/string_utils.cpp index 717405f4..617b1b00 100644 --- a/src/string_utils.cpp +++ b/src/string_utils.cpp @@ -180,6 +180,12 @@ void StringUtils::split_to_values(const std::string& vals_str, std::vector, char32_t> utf8conv; return utf8conv.from_bytes(bytes).size(); diff --git a/test/collection_faceting_test.cpp b/test/collection_faceting_test.cpp index bfbcb1ca..3aba9e64 100644 --- a/test/collection_faceting_test.cpp +++ b/test/collection_faceting_test.cpp @@ -404,6 +404,42 @@ TEST_F(CollectionFacetingTest, FacetCountsBool) { collectionManager.drop_collection("coll1"); } +TEST_F(CollectionFacetingTest, FacetCountsFloatPrecision) { + Collection *coll1; + + std::vector fields = {field("title", field_types::STRING, false), + field("points", field_types::FLOAT, true)}; + + std::vector sort_fields = {sort_by("points", "DESC")}; + + coll1 = collectionManager.get_collection("coll1").get(); + if (coll1 == nullptr) { + coll1 = collectionManager.create_collection("coll1", 4, fields, "points").get(); + } + + nlohmann::json doc; + doc["id"] = "100"; + doc["title"] = "Ford Mustang"; + doc["points"] = 113.4; + + coll1->add(doc.dump()); + + std::vector facets = {"points"}; + + nlohmann::json results = coll1->search("*", {"title"}, "", facets, sort_fields, {0}, 10, 1, + token_ordering::FREQUENCY, true).get(); + + ASSERT_EQ(1, results["facet_counts"].size()); + ASSERT_EQ(1, results["facet_counts"][0]["counts"].size()); + + ASSERT_STREQ("points", results["facet_counts"][0]["field_name"].get().c_str()); + ASSERT_EQ(1, (int) results["facet_counts"][0]["counts"][0]["count"]); + ASSERT_STREQ("113.4", results["facet_counts"][0]["counts"][0]["value"].get().c_str()); + ASSERT_STREQ("113.4",results["facet_counts"][0]["counts"][0]["highlighted"].get().c_str()); + + collectionManager.drop_collection("coll1"); +} + TEST_F(CollectionFacetingTest, FacetCountsHighlighting) { Collection *coll1;