summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGeir Storli <geirst@oath.com>2018-06-08 12:56:36 +0000
committerGeir Storli <geirst@oath.com>2018-06-08 12:56:36 +0000
commit29649971ad58d3c24f6393a06b063b346d1be96b (patch)
tree98248049c861e5a0e3e542eada86efd995d0fa79
parentf923ea8a4b4c3a94a5beabef70f77e9f49bde407 (diff)
Support handling map of primitive types in document field extractor.
-rw-r--r--searchcore/src/tests/proton/attribute/document_field_extractor/document_field_extractor_test.cpp38
-rw-r--r--searchcore/src/vespa/searchcore/proton/attribute/document_field_extractor.cpp38
-rw-r--r--searchcore/src/vespa/searchcore/proton/attribute/document_field_extractor.h3
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: