From 2a75f6fc73682777235765ead1f64e71c95f406e Mon Sep 17 00:00:00 2001 From: Kishore Nallan Date: Fri, 10 Feb 2023 17:03:29 +0530 Subject: [PATCH 1/2] Fix boolean field as default sorting field. --- src/index.cpp | 3 ++- test/collection_sorting_test.cpp | 14 ++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/index.cpp b/src/index.cpp index 9e539236..749ca44d 100644 --- a/src/index.cpp +++ b/src/index.cpp @@ -215,7 +215,8 @@ int64_t Index::get_points_from_doc(const nlohmann::json &document, const std::st // not much value in supporting default sorting field as string, so we will just dummy it out points = 0; } else { - points = document[default_sorting_field]; + points = document[default_sorting_field].is_boolean() ? int64_t(document[default_sorting_field].get()) : + document[default_sorting_field].get(); } return points; diff --git a/test/collection_sorting_test.cpp b/test/collection_sorting_test.cpp index afd678c1..8bd805a9 100644 --- a/test/collection_sorting_test.cpp +++ b/test/collection_sorting_test.cpp @@ -124,6 +124,7 @@ TEST_F(CollectionSortingTest, DefaultSortingFieldValidations) { std::vector fields = {field("name", field_types::STRING, false), field("tags", field_types::STRING_ARRAY, true), field("age", field_types::INT32, false), + field("in_stock", field_types::BOOL, false), field("average", field_types::INT32, false) }; std::vector sort_fields = { sort_by("age", "DESC"), sort_by("average", "DESC") }; @@ -140,6 +141,19 @@ TEST_F(CollectionSortingTest, DefaultSortingFieldValidations) { ASSERT_FALSE(collection_op.ok()); ASSERT_EQ("Default sorting field is defined as `NOT-DEFINED` but is not found in the schema.", collection_op.error()); collectionManager.drop_collection("sample_collection"); + + // must be able to use boolean field as default sorting field + collection_op = collectionManager.create_collection("sample_collection", 4, fields, "in_stock"); + ASSERT_TRUE(collection_op.ok()); + auto coll = collection_op.get(); + nlohmann::json doc; + doc["name"] = "Example"; + doc["tags"] = {"example"}; + doc["age"] = 100; + doc["in_stock"] = true; + doc["average"] = 45; + + ASSERT_TRUE(coll->add(doc.dump()).ok()); } TEST_F(CollectionSortingTest, NoDefaultSortingField) { From a121f95bd8c7789e3e8505c003ae5c41d164794d Mon Sep 17 00:00:00 2001 From: Kishore Nallan Date: Sun, 12 Feb 2023 07:51:05 +0530 Subject: [PATCH 2/2] Don't remove empty array of obj elements for highlight. --- src/collection.cpp | 5 +- test/collection_nested_fields_test.cpp | 98 +++++++++++++++++++++++++- 2 files changed, 97 insertions(+), 6 deletions(-) diff --git a/src/collection.cpp b/src/collection.cpp index 5a1d8a54..db5f9046 100644 --- a/src/collection.cpp +++ b/src/collection.cpp @@ -3535,10 +3535,7 @@ void Collection::prune_doc(nlohmann::json& doc, if(arr_it.value().is_object()) { bool orig_ele_empty = arr_it.value().empty(); prune_doc(arr_it.value(), include_names, exclude_names, nested_name, depth+1); - if(!orig_ele_empty && arr_it.value().empty()) { - arr_it = it.value().erase(arr_it); - continue; - } + // don't remove empty array objects to help frontend } arr_it++; diff --git a/test/collection_nested_fields_test.cpp b/test/collection_nested_fields_test.cpp index 678b93bb..49a7eef9 100644 --- a/test/collection_nested_fields_test.cpp +++ b/test/collection_nested_fields_test.cpp @@ -615,7 +615,8 @@ TEST_F(CollectionNestedFieldsTest, IncludeExcludeFieldsPruning) { auto doc = nlohmann::json::parse(doc_str); Collection::prune_doc(doc, tsl::htrie_set(), {"one_obj_arr.foo"}); - ASSERT_EQ(0, doc.count("one_obj_arr")); + ASSERT_EQ(1, doc.count("one_obj_arr")); + ASSERT_EQ(1, doc["one_obj_arr"].size()); // handle non-existing exclude field doc = nlohmann::json::parse(doc_str); @@ -637,7 +638,7 @@ TEST_F(CollectionNestedFieldsTest, IncludeExcludeFieldsPruning) { // exclusion takes preference doc = nlohmann::json::parse(doc_str); Collection::prune_doc(doc, {"locations.address.city"}, {"locations.address.city"}); - ASSERT_EQ(R"({})", doc.dump()); + ASSERT_EQ(R"({"locations":[{},{}]})", doc.dump()); // include object, exclude sub-fields doc = nlohmann::json::parse(doc_str); @@ -2327,12 +2328,105 @@ TEST_F(CollectionNestedFieldsTest, UpdateNestedDocument) { results = coll1->search("shaw", {"contributors"}, "", {}, {}, {0}, 10, 1, FREQUENCY, {false}).get(); ASSERT_EQ(1, results["found"].get()); + results = coll1->search("john", {"contributors.first_name"}, "", {}, {}, {0}, 10, 1, FREQUENCY, {false}).get(); + ASSERT_EQ(1, results["found"].get()); + // should not be able to find the old name results = coll1->search("galt", {"contributors"}, "", {}, {}, {0}, 10, 1, FREQUENCY, {false}).get(); ASSERT_EQ(0, results["found"].get()); } +TEST_F(CollectionNestedFieldsTest, UpdateNestedDocumentAutoSchema) { + nlohmann::json schema = R"({ + "name": "coll1", + "enable_nested_fields": true, + "fields": [ + {"name": ".*", "type": "auto"} + ] + })"_json; + + auto op = collectionManager.create_collection(schema); + ASSERT_TRUE(op.ok()); + Collection* coll1 = op.get(); + + auto doc1 = R"({ + "id": "0", + "price": {"now": 3000, "country": "US"} + })"_json; + + auto add_op = coll1->add(doc1.dump(), CREATE); + ASSERT_TRUE(add_op.ok()); + + // update document partially + + doc1 = R"({ + "id": "0", + "price": {"now": 4000} + })"_json; + + add_op = coll1->add(doc1.dump(), UPDATE); + ASSERT_TRUE(add_op.ok()); + + auto results = coll1->search("us", {"price.country"}, "", {}, {}, {0}, 10, 1, FREQUENCY, {false}).get(); + ASSERT_EQ(1, results["found"].get()); +} + +TEST_F(CollectionNestedFieldsTest, HighlightArrayOfObjects) { + nlohmann::json schema = R"({ + "name": "coll1", + "enable_nested_fields": true, + "fields": [ + {"name": ".*", "type": "auto"} + ] + })"_json; + + auto op = collectionManager.create_collection(schema); + ASSERT_TRUE(op.ok()); + Collection* coll1 = op.get(); + + auto doc1 = R"({ + "details": [ + {"foo": "John Smith"}, + {"name": "James Peterson"}, + {"bar": "John Galt"} + ] + })"_json; + + auto add_op = coll1->add(doc1.dump(), CREATE); + ASSERT_TRUE(add_op.ok()); + + auto results = coll1->search("james", {"details.name"}, "", {}, {}, {0}, 10, 1, FREQUENCY, + {true}, 1, spp::sparse_hash_set(), + spp::sparse_hash_set(), 10, "", 30, 4).get(); + ASSERT_EQ(1, results["found"].get()); + ASSERT_EQ(3, results["hits"][0]["highlight"]["details"].size()); + ASSERT_EQ(0, results["hits"][0]["highlight"]["details"][0].size()); + ASSERT_EQ(1, results["hits"][0]["highlight"]["details"][1].size()); + ASSERT_EQ(0, results["hits"][0]["highlight"]["details"][2].size()); + + results = coll1->search("james", {"details.name"}, "", {}, {}, {0}, 10, 1, FREQUENCY, + {true}, 1, spp::sparse_hash_set(), + spp::sparse_hash_set(), 10, "", 30, 4, "", 1, {}, {}, {}, 0, + "", "", {1}, 10000, true, false, true, "details.name").get(); + + ASSERT_EQ(1, results["found"].get()); + ASSERT_EQ(0, results["hits"][0]["highlight"]["details"][0].size()); + ASSERT_EQ(1, results["hits"][0]["highlight"]["details"][1].size()); + ASSERT_EQ(0, results["hits"][0]["highlight"]["details"][2].size()); + + results = coll1->search("james", {"details.name"}, "", {}, {}, {0}, 10, 1, FREQUENCY, + {true}, 1, spp::sparse_hash_set(), + spp::sparse_hash_set(), 10, "", 30, 4, "", 1, {}, {}, {}, 0, + "", "", {1}, 10000, true, false, true, "details").get(); + + ASSERT_EQ(1, results["found"].get()); + ASSERT_EQ(3, results["hits"][0]["highlight"]["details"].size()); + ASSERT_EQ(1, results["hits"][0]["highlight"]["details"][0].size()); + ASSERT_EQ(1, results["hits"][0]["highlight"]["details"][1].size()); + ASSERT_EQ(1, results["hits"][0]["highlight"]["details"][2].size()); +} + TEST_F(CollectionNestedFieldsTest, HighlightOnFlatFieldWithSnippeting) { std::vector fields = {field("title", field_types::STRING, false), field("body", field_types::STRING, false)};