From 2254d259556a93093058243ed51065cfe5b0fe9e Mon Sep 17 00:00:00 2001 From: Kishore Nallan Date: Thu, 2 Nov 2023 16:13:04 +0530 Subject: [PATCH] Handle null values in nested object arrays for optional fields. --- src/field.cpp | 5 +- test/collection_nested_fields_test.cpp | 102 +++++++++++++++++++++++++ 2 files changed, 104 insertions(+), 3 deletions(-) diff --git a/src/field.cpp b/src/field.cpp index d053e578..ea99b72f 100644 --- a/src/field.cpp +++ b/src/field.cpp @@ -833,9 +833,8 @@ bool field::flatten_obj(nlohmann::json& doc, nlohmann::json& value, bool has_arr while(it != value.end()) { const std::string& child_field_name = flat_name + "." + it.key(); if(it.value().is_null()) { - if(has_array) { - doc[child_field_name].push_back(nullptr); - } else { + if(!has_array) { + // we don't want to push null values into an array because that's not valid doc[child_field_name] = nullptr; } diff --git a/test/collection_nested_fields_test.cpp b/test/collection_nested_fields_test.cpp index 98a94f37..1c4bfb24 100644 --- a/test/collection_nested_fields_test.cpp +++ b/test/collection_nested_fields_test.cpp @@ -1487,6 +1487,108 @@ TEST_F(CollectionNestedFieldsTest, ExplicitSchemaForNestedArrayTypeValidation) { "Hint: field inside an array of objects must be an array type as well.", add_op.error()); } +TEST_F(CollectionNestedFieldsTest, OptionalNestedOptionalOjectArrStringField) { + nlohmann::json schema = R"({ + "name": "coll1", + "enable_nested_fields": true, + "fields": [ + {"facet":true,"name":"data","optional":false,"type":"object"}, + {"facet":false,"name":"data.locations.stateShort","optional":true,"type":"string[]"} + ] + })"_json; + + auto op = collectionManager.create_collection(schema); + ASSERT_TRUE(op.ok()); + Collection* coll1 = op.get(); + + auto doc1 = R"({ + "data": { + "locations": [ + { + "stateShort": null + } + ] + } + })"_json; + + auto add_op = coll1->add(doc1.dump(), CREATE); + ASSERT_TRUE(add_op.ok()); + + doc1 = R"({ + "data": { + "locations": [ + { + "stateShort": null + }, + { + "stateShort": "NY" + } + ] + } + })"_json; + + coll1->add(doc1.dump(), CREATE); + + auto results = coll1->search("ny", {"data.locations.stateShort"}, + "", {}, {}, {0}, 10, 1, + token_ordering::FREQUENCY, {true}, 10, spp::sparse_hash_set(), + spp::sparse_hash_set(), 10, "", 30, 4).get(); + + ASSERT_EQ(1, results["found"].get()); +} + +TEST_F(CollectionNestedFieldsTest, OptionalNestedNonOptionalOjectArrStringField) { + nlohmann::json schema = R"({ + "name": "coll1", + "enable_nested_fields": true, + "fields": [ + {"facet":true,"name":"data","type":"object"}, + {"facet":false,"name":"data.locations.stateShort","type":"string[]"} + ] + })"_json; + + auto op = collectionManager.create_collection(schema); + ASSERT_TRUE(op.ok()); + Collection* coll1 = op.get(); + + auto doc1 = R"({ + "data": { + "locations": [ + { + "stateShort": null + } + ] + } + })"_json; + + auto add_op = coll1->add(doc1.dump(), CREATE); + ASSERT_FALSE(add_op.ok()); + ASSERT_EQ("Field `data.locations.stateShort` has been declared in the schema, but is not found in the document.", + add_op.error()); + + doc1 = R"({ + "data": { + "locations": [ + { + "stateShort": null + }, + { + "stateShort": "NY" + } + ] + } + })"_json; + + coll1->add(doc1.dump(), CREATE); + + auto results = coll1->search("ny", {"data.locations.stateShort"}, + "", {}, {}, {0}, 10, 1, + token_ordering::FREQUENCY, {true}, 10, spp::sparse_hash_set(), + spp::sparse_hash_set(), 10, "", 30, 4).get(); + + ASSERT_EQ(1, results["found"].get()); +} + TEST_F(CollectionNestedFieldsTest, SortByNestedField) { nlohmann::json schema = R"({ "name": "coll1",