diff options
author | Geir Storli <geirst@oath.com> | 2018-06-08 12:56:36 +0000 |
---|---|---|
committer | Geir Storli <geirst@oath.com> | 2018-06-08 12:56:36 +0000 |
commit | 29649971ad58d3c24f6393a06b063b346d1be96b (patch) | |
tree | 98248049c861e5a0e3e542eada86efd995d0fa79 | |
parent | f923ea8a4b4c3a94a5beabef70f77e9f49bde407 (diff) |
Support handling map of primitive types in document field extractor.
3 files changed, 67 insertions, 12 deletions
diff --git a/searchcore/src/tests/proton/attribute/document_field_extractor/document_field_extractor_test.cpp b/searchcore/src/tests/proton/attribute/document_field_extractor/document_field_extractor_test.cpp index bad27938d4b..33a3de0c5b6 100644 --- a/searchcore/src/tests/proton/attribute/document_field_extractor/document_field_extractor_test.cpp +++ b/searchcore/src/tests/proton/attribute/document_field_extractor/document_field_extractor_test.cpp @@ -36,8 +36,7 @@ using document::FieldValue; using document::FieldNotFoundException; using proton::DocumentFieldExtractor; -namespace -{ +namespace { const ArrayDataType arrayTypeInt(*DataType::INT); const ArrayDataType arrayTypeString(*DataType::STRING); @@ -335,6 +334,41 @@ TEST_F("require that struct map field gives array values", StructMapFixture) TEST_DO(f.assertExtracted("s.value.name", makeStringArray({ "name10", noString, "name12", noString }))); } +struct PrimitiveMapFixture : public FixtureBase +{ + MapDataType mapFieldType; + Field mapField; + using MapVector = std::vector<std::pair<vespalib::string, int>>; + + PrimitiveMapFixture() + : FixtureBase(false), + mapFieldType(nameField.getDataType(), weightField.getDataType()), + mapField("map", mapFieldType, true) + { + type.addField(mapField); + } + + std::unique_ptr<MapFieldValue> makeMap(const MapVector &input) { + auto result = std::make_unique<MapFieldValue>(mapFieldType); + for (const auto &elem : input) { + result->put(StringFieldValue(elem.first), IntFieldValue(elem.second)); + } + return result; + } + + void makeDoc(const MapVector &input) { + FixtureBase::makeDoc()->setValue(mapField, *makeMap(input)); + } + +}; + +TEST_F("require that primitive map field gives array values", PrimitiveMapFixture) +{ + f.makeDoc({ {"foo", 10}, {"", 20}, {"bar", noInt} }); + TEST_DO(f.assertExtracted("map.key", makeStringArray({ "foo", "", "bar" }))); + TEST_DO(f.assertExtracted("map.value", makeIntArray({ 10, 20, noInt }))); +} + TEST_F("require that unknown field gives null value", FixtureBase(false)) { f.makeDoc(); diff --git a/searchcore/src/vespa/searchcore/proton/attribute/document_field_extractor.cpp b/searchcore/src/vespa/searchcore/proton/attribute/document_field_extractor.cpp index 46f3fdeff67..5bef5604e42 100644 --- a/searchcore/src/vespa/searchcore/proton/attribute/document_field_extractor.cpp +++ b/searchcore/src/vespa/searchcore/proton/attribute/document_field_extractor.cpp @@ -11,12 +11,10 @@ #include <vespa/document/fieldvalue/longfieldvalue.h> #include <vespa/document/fieldvalue/shortfieldvalue.h> #include <vespa/document/fieldvalue/stringfieldvalue.h> -#include <vespa/document/fieldvalue/structfieldvalue.h> #include <vespa/document/fieldvalue/mapfieldvalue.h> #include <vespa/searchcommon/common/undefinedvalues.h> #include <vespa/vespalib/stllike/hash_map.hpp> #include <vespa/vespalib/util/exceptions.h> -#include <vespa/vespalib/util/stringfmt.h> using document::FieldValue; using document::ByteFieldValue; @@ -132,7 +130,8 @@ DocumentFieldExtractor::isSupported(const FieldPath &fieldPath) } if (fieldPath.size() == 2) { if (fieldPath[1].getType() != FieldPathEntry::Type::STRUCT_FIELD && - fieldPath[1].getType() != FieldPathEntry::Type::MAP_ALL_KEYS) { + fieldPath[1].getType() != FieldPathEntry::Type::MAP_ALL_KEYS && + fieldPath[1].getType() != FieldPathEntry::Type::MAP_ALL_VALUES) { return false; } } else if (fieldPath.size() == 3) { @@ -186,22 +185,40 @@ DocumentFieldExtractor::getStructArrayFieldValue(const FieldPath &fieldPath) return std::unique_ptr<FieldValue>(); } +namespace { + +template <typename ExtractorFunc> std::unique_ptr<FieldValue> -DocumentFieldExtractor::getStructMapKeyFieldValue(const FieldPath &fieldPath) +getMapFieldValue(const FieldValue *outerFieldValue, const FieldPathEntry &innerEntry, ExtractorFunc &&extractor) { - const auto outerFieldValue = getCachedFieldValue(fieldPath[0]); if (outerFieldValue != nullptr && checkInherits(*outerFieldValue, MapFieldValue::classId)) { const auto outerMap = static_cast<const MapFieldValue *>(outerFieldValue); - auto array = makeArray(fieldPath[1], outerMap->size()); + auto array = makeArray(innerEntry, outerMap->size()); uint32_t arrayIndex = 0; for (const auto &mapElem : *outerMap) { - (*array)[arrayIndex++].assign(*mapElem.first); + (*array)[arrayIndex++].assign(*extractor(mapElem)); } return array; } return std::unique_ptr<FieldValue>(); } +} + +std::unique_ptr<FieldValue> +DocumentFieldExtractor::getMapKeyFieldValue(const FieldPath &fieldPath) +{ + return getMapFieldValue(getCachedFieldValue(fieldPath[0]), fieldPath[1], + [](const auto &elem){ return elem.first; }); +} + +std::unique_ptr<document::FieldValue> +DocumentFieldExtractor::getPrimitiveMapFieldValue(const FieldPath &fieldPath) +{ + return getMapFieldValue(getCachedFieldValue(fieldPath[0]), fieldPath[1], + [](const auto &elem){ return elem.second; }); +} + std::unique_ptr<document::FieldValue> DocumentFieldExtractor::getStructMapFieldValue(const FieldPath &fieldPath) { @@ -229,10 +246,13 @@ DocumentFieldExtractor::getFieldValue(const FieldPath &fieldPath) if (fieldPath.size() == 1) { return getSimpleFieldValue(fieldPath); } else if (fieldPath.size() == 2) { - if (fieldPath[1].getType() == FieldPathEntry::Type::STRUCT_FIELD) { + auto lastElemType = fieldPath[1].getType(); + if (lastElemType == FieldPathEntry::Type::STRUCT_FIELD) { return getStructArrayFieldValue(fieldPath); + } else if (lastElemType == FieldPathEntry::Type::MAP_ALL_KEYS) { + return getMapKeyFieldValue(fieldPath); } else { - return getStructMapKeyFieldValue(fieldPath); + return getPrimitiveMapFieldValue(fieldPath); } } else if (fieldPath.size() == 3) { return getStructMapFieldValue(fieldPath); diff --git a/searchcore/src/vespa/searchcore/proton/attribute/document_field_extractor.h b/searchcore/src/vespa/searchcore/proton/attribute/document_field_extractor.h index 48e2da9c4c6..da94dda7d31 100644 --- a/searchcore/src/vespa/searchcore/proton/attribute/document_field_extractor.h +++ b/searchcore/src/vespa/searchcore/proton/attribute/document_field_extractor.h @@ -28,7 +28,8 @@ class DocumentFieldExtractor const document::FieldValue *getCachedFieldValue(const document::FieldPathEntry &fieldPathEntry); std::unique_ptr<document::FieldValue> getSimpleFieldValue(const document::FieldPath &fieldPath); std::unique_ptr<document::FieldValue> getStructArrayFieldValue(const document::FieldPath &fieldPath); - std::unique_ptr<document::FieldValue> getStructMapKeyFieldValue(const document::FieldPath &fieldPath); + std::unique_ptr<document::FieldValue> getMapKeyFieldValue(const document::FieldPath &fieldPath); + std::unique_ptr<document::FieldValue> getPrimitiveMapFieldValue(const document::FieldPath &fieldPath); std::unique_ptr<document::FieldValue> getStructMapFieldValue(const document::FieldPath &fieldPath); public: |