mirror of
https://github.com/typesense/typesense.git
synced 2025-05-20 05:32:30 +08:00
Better error messages for nested field type mismatch.
This commit is contained in:
parent
f9f7afff52
commit
aeb4424662
@ -398,9 +398,9 @@ struct field {
|
||||
static bool flatten_obj(nlohmann::json& doc, nlohmann::json& value, bool has_array, bool has_obj_array,
|
||||
const std::string& flat_name, std::unordered_map<std::string, field>& flattened_fields);
|
||||
|
||||
static bool flatten_field(nlohmann::json& doc, nlohmann::json& obj, const field& the_field,
|
||||
std::vector<std::string>& path_parts, size_t path_index, bool has_array,
|
||||
bool has_obj_array, std::unordered_map<std::string, field>& flattened_fields);
|
||||
static Option<bool> flatten_field(nlohmann::json& doc, nlohmann::json& obj, const field& the_field,
|
||||
std::vector<std::string>& path_parts, size_t path_index, bool has_array,
|
||||
bool has_obj_array, std::unordered_map<std::string, field>& flattened_fields);
|
||||
|
||||
static Option<bool> flatten_doc(nlohmann::json& document, const std::vector<field>& nested_fields,
|
||||
std::vector<field>& flattened_fields);
|
||||
|
@ -612,14 +612,14 @@ bool field::flatten_obj(nlohmann::json& doc, nlohmann::json& value, bool has_arr
|
||||
return true;
|
||||
}
|
||||
|
||||
bool field::flatten_field(nlohmann::json& doc, nlohmann::json& obj, const field& the_field,
|
||||
Option<bool> field::flatten_field(nlohmann::json& doc, nlohmann::json& obj, const field& the_field,
|
||||
std::vector<std::string>& path_parts, size_t path_index,
|
||||
bool has_array, bool has_obj_array, std::unordered_map<std::string, field>& flattened_fields) {
|
||||
if(path_index == path_parts.size()) {
|
||||
// end of path: check if obj matches expected type
|
||||
std::string detected_type;
|
||||
if(!field::get_type(obj, detected_type)) {
|
||||
return false;
|
||||
return Option<bool>(400, "Field `" + the_field.name + "` has an incorrect type.");
|
||||
}
|
||||
|
||||
if(std::isalnum(detected_type.back()) && has_array) {
|
||||
@ -641,7 +641,7 @@ bool field::flatten_field(nlohmann::json& doc, nlohmann::json& obj, const field&
|
||||
flatten_obj(doc, obj, has_array, has_obj_array, the_field.name, flattened_fields);
|
||||
} else {
|
||||
if(doc.count(the_field.name) != 0 && flattened_fields.find(the_field.name) == flattened_fields.end()) {
|
||||
return true;
|
||||
return Option<bool>(true);
|
||||
}
|
||||
|
||||
if(has_array) {
|
||||
@ -656,9 +656,14 @@ bool field::flatten_field(nlohmann::json& doc, nlohmann::json& obj, const field&
|
||||
flattened_fields[the_field.name] = flattened_field;
|
||||
}
|
||||
|
||||
return true;
|
||||
return Option<bool>(true);
|
||||
} else {
|
||||
return false;
|
||||
if(has_obj_array && !the_field.is_array()) {
|
||||
return Option<bool>(400, "Field `" + the_field.name + "` has an incorrect type. "
|
||||
"Hint: field inside an array of objects must be an array type as well.");
|
||||
}
|
||||
|
||||
return Option<bool>(400, "Field `" + the_field.name + "` has an incorrect type.");
|
||||
}
|
||||
}
|
||||
|
||||
@ -667,18 +672,25 @@ bool field::flatten_field(nlohmann::json& doc, nlohmann::json& obj, const field&
|
||||
|
||||
if(it != obj.end()) {
|
||||
if(it.value().is_array()) {
|
||||
if(it.value().empty()) {
|
||||
return Option<bool>(404, "Field `" + the_field.name + "` not found.");
|
||||
}
|
||||
|
||||
has_array = true;
|
||||
bool resolved = false;
|
||||
for(auto& ele: it.value()) {
|
||||
has_obj_array = has_obj_array || ele.is_object();
|
||||
resolved |= flatten_field(doc, ele, the_field, path_parts, path_index + 1, has_array, has_obj_array, flattened_fields);
|
||||
Option<bool> op = flatten_field(doc, ele, the_field, path_parts, path_index + 1, has_array,
|
||||
has_obj_array, flattened_fields);
|
||||
if(!op.ok()) {
|
||||
return op;
|
||||
}
|
||||
}
|
||||
return resolved;
|
||||
return Option<bool>(true);
|
||||
} else {
|
||||
return flatten_field(doc, it.value(), the_field, path_parts, path_index + 1, has_array, has_obj_array, flattened_fields);
|
||||
}
|
||||
} {
|
||||
return false;
|
||||
return Option<bool>(404, "Field `" + the_field.name + "` not found.");
|
||||
}
|
||||
}
|
||||
|
||||
@ -697,9 +709,15 @@ Option<bool> field::flatten_doc(nlohmann::json& document,
|
||||
continue;
|
||||
}
|
||||
|
||||
bool resolved = flatten_field(document, document, nested_field, field_parts, 0, false, false, flattened_fields_map);
|
||||
if(!resolved && !nested_field.optional) {
|
||||
return Option<bool>(400, "Field `" + nested_field.name + "` was not found or has an incorrect type.");
|
||||
auto op = flatten_field(document, document, nested_field, field_parts, 0, false, false, flattened_fields_map);
|
||||
if(op.ok()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if(op.code() == 404 && nested_field.optional) {
|
||||
continue;
|
||||
} else {
|
||||
return op;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -279,7 +279,7 @@ TEST_F(CollectionNestedFieldsTest, FlattenJSONObjectHandleErrors) {
|
||||
nlohmann::json doc = nlohmann::json::parse(json_str);
|
||||
auto flatten_op = field::flatten_doc(doc, nested_fields, flattened_fields);
|
||||
ASSERT_FALSE(flatten_op.ok());
|
||||
ASSERT_EQ("Field `locations` was not found or has an incorrect type.", flatten_op.error());
|
||||
ASSERT_EQ("Field `locations` not found.", flatten_op.error());
|
||||
|
||||
nested_fields = {
|
||||
field("company", field_types::INT32, false)
|
||||
@ -288,7 +288,7 @@ TEST_F(CollectionNestedFieldsTest, FlattenJSONObjectHandleErrors) {
|
||||
flattened_fields.clear();
|
||||
flatten_op = field::flatten_doc(doc, nested_fields, flattened_fields);
|
||||
ASSERT_FALSE(flatten_op.ok());
|
||||
ASSERT_EQ("Field `company` was not found or has an incorrect type.", flatten_op.error());
|
||||
ASSERT_EQ("Field `company` has an incorrect type.", flatten_op.error());
|
||||
}
|
||||
|
||||
TEST_F(CollectionNestedFieldsTest, SearchOnFieldsOnWildcardSchema) {
|
||||
@ -937,7 +937,7 @@ TEST_F(CollectionNestedFieldsTest, FieldsWithExplicitSchema) {
|
||||
|
||||
add_op = coll3->add(doc2.dump(), CREATE);
|
||||
ASSERT_FALSE(add_op.ok());
|
||||
ASSERT_EQ("Field `details` was not found or has an incorrect type.", add_op.error());
|
||||
ASSERT_EQ("Field `details` not found.", add_op.error());
|
||||
|
||||
// check fields and their properties
|
||||
auto coll_fields = coll1->get_fields();
|
||||
@ -1452,3 +1452,53 @@ TEST_F(CollectionNestedFieldsTest, UpdateOfNestFields) {
|
||||
results = coll1->search("*", {}, "company.num_employees: 2000", {}, {}, {0}, 10, 1, FREQUENCY, {false}).get();
|
||||
ASSERT_EQ(1, results["found"].get<size_t>());
|
||||
}
|
||||
|
||||
TEST_F(CollectionNestedFieldsTest, NestedSchemaWithSingularType) {
|
||||
nlohmann::json schema = R"({
|
||||
"name": "coll1",
|
||||
"enable_nested_fields": true,
|
||||
"fields": [
|
||||
{"name": "studies.year", "type": "int32", "optional": false}
|
||||
]
|
||||
})"_json;
|
||||
|
||||
auto op = collectionManager.create_collection(schema);
|
||||
ASSERT_TRUE(op.ok());
|
||||
Collection* coll1 = op.get();
|
||||
|
||||
auto doc1 = R"({
|
||||
"id": "0",
|
||||
"studies": [{"name": "College 1", "year": 1997}]
|
||||
})"_json;
|
||||
|
||||
auto add_op = coll1->add(doc1.dump(), CREATE);
|
||||
ASSERT_FALSE(add_op.ok());
|
||||
ASSERT_EQ("Field `studies.year` has an incorrect type. "
|
||||
"Hint: field inside an array of objects must be an array type as well.", add_op.error());
|
||||
|
||||
// even when field is optional, there should be an error
|
||||
schema = R"({
|
||||
"name": "coll2",
|
||||
"enable_nested_fields": true,
|
||||
"fields": [
|
||||
{"name": "studies.year", "type": "int32", "optional": true}
|
||||
]
|
||||
})"_json;
|
||||
|
||||
op = collectionManager.create_collection(schema);
|
||||
ASSERT_TRUE(op.ok());
|
||||
Collection* coll2 = op.get();
|
||||
add_op = coll2->add(doc1.dump(), CREATE);
|
||||
ASSERT_FALSE(add_op.ok());
|
||||
ASSERT_EQ("Field `studies.year` has an incorrect type. "
|
||||
"Hint: field inside an array of objects must be an array type as well.", add_op.error());
|
||||
|
||||
// allow optional field to be missing when value is singular
|
||||
doc1 = R"({
|
||||
"id": "0",
|
||||
"studies": {"name": "College 1"}
|
||||
})"_json;
|
||||
|
||||
add_op = coll2->add(doc1.dump(), CREATE);
|
||||
ASSERT_TRUE(add_op.ok());
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user