diff options
author | Arne H Juul <arnej27959@users.noreply.github.com> | 2022-01-19 09:54:55 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-01-19 09:54:55 +0100 |
commit | e79d967e99c27412e502d4aaa32b6a60d88fcbbb (patch) | |
tree | f9ec474e290bb9aec886f57ff8f538d0a87ead5c | |
parent | 4cc7565cfe27aef8809337f3d926dbfff18f3b9a (diff) | |
parent | 7572116c9c76967ec986803103bcbc3427083762 (diff) |
Merge pull request #20861 from vespa-engine/arnej/special-document-only-fieldset
add special '[document]' fieldset
8 files changed, 74 insertions, 12 deletions
diff --git a/document/src/vespa/document/base/field.cpp b/document/src/vespa/document/base/field.cpp index 5c696d80fe7..86b1d93eacf 100644 --- a/document/src/vespa/document/base/field.cpp +++ b/document/src/vespa/document/base/field.cpp @@ -79,6 +79,7 @@ Field::contains(const FieldSet& fields) const case Type::NONE: case Type::DOCID: return true; + case Type::DOCUMENT_ONLY: case Type::ALL: return false; } diff --git a/document/src/vespa/document/datatype/documenttype.cpp b/document/src/vespa/document/datatype/documenttype.cpp index 81389d25bd7..1c43e2dfc64 100644 --- a/document/src/vespa/document/datatype/documenttype.cpp +++ b/document/src/vespa/document/datatype/documenttype.cpp @@ -14,8 +14,30 @@ using vespalib::IllegalArgumentException; using vespalib::make_string; using vespalib::stringref; + namespace document { +namespace { +FieldCollection build_field_collection(const std::set<vespalib::string> &fields, + const DocumentType &doc_type) +{ + Field::Set::Builder builder; + for (const auto & field_name : fields) { + if (doc_type.hasField(field_name)) { + builder.add(&doc_type.getField(field_name)); + } + } + return FieldCollection(doc_type, builder.build()); +} +} // namespace <unnamed> + +DocumentType::FieldSet::FieldSet(const vespalib::string & name, Fields fields, + const DocumentType & doc_type) + : _name(name), + _fields(fields), + _field_collection(build_field_collection(fields, doc_type)) +{} + IMPLEMENT_IDENTIFIABLE(DocumentType, StructuredDataType); DocumentType::DocumentType() = default; @@ -75,7 +97,7 @@ DocumentType::~DocumentType() = default; DocumentType & DocumentType::addFieldSet(const vespalib::string & name, FieldSet::Fields fields) { - _fieldSets[name] = FieldSet(name, std::move(fields)); + _fieldSets.emplace(name, FieldSet(name, std::move(fields), *this)); return *this; } diff --git a/document/src/vespa/document/datatype/documenttype.h b/document/src/vespa/document/datatype/documenttype.h index 28a0f0c9d55..bddc0a26e99 100644 --- a/document/src/vespa/document/datatype/documenttype.h +++ b/document/src/vespa/document/datatype/documenttype.h @@ -11,6 +11,7 @@ #pragma once +#include <vespa/document/fieldset/fieldsets.h> #include <vespa/document/datatype/structdatatype.h> #include <vespa/vespalib/stllike/hash_set.h> #include <vespa/vespalib/stllike/string.h> @@ -28,23 +29,19 @@ public: class FieldSet { public: using Fields = std::set<vespalib::string>; - FieldSet() = default; - explicit FieldSet(const vespalib::string & name) : _name(name), _fields() {} - FieldSet(const vespalib::string & name, Fields fields) : _name(name), _fields(std::move(fields)) {} + FieldSet(const vespalib::string & name, Fields fields, + const DocumentType & doc_type); + FieldSet(const FieldSet&) = default; - FieldSet& operator=(const FieldSet&) = default; FieldSet(FieldSet&&) noexcept = default; - FieldSet& operator=(FieldSet&&) noexcept = default; const vespalib::string & getName() const noexcept { return _name; } const Fields & getFields() const noexcept { return _fields; } - FieldSet & add(vespalib::string & field) { - _fields.insert(field); - return *this; - } + const FieldCollection & asCollection() const { return _field_collection; } private: vespalib::string _name; Fields _fields; + FieldCollection _field_collection; }; using FieldSetMap = std::map<vespalib::string, FieldSet>; using ImportedFieldNames = vespalib::hash_set<vespalib::string>; diff --git a/document/src/vespa/document/fieldset/fieldset.h b/document/src/vespa/document/fieldset/fieldset.h index fd604a19e08..1f53f7a3456 100644 --- a/document/src/vespa/document/fieldset/fieldset.h +++ b/document/src/vespa/document/fieldset/fieldset.h @@ -20,7 +20,8 @@ public: SET, ALL, NONE, - DOCID + DOCID, + DOCUMENT_ONLY }; using SP = std::shared_ptr<FieldSet>; diff --git a/document/src/vespa/document/fieldset/fieldsetrepo.cpp b/document/src/vespa/document/fieldset/fieldsetrepo.cpp index 97b7fa09813..851eb8f4ecf 100644 --- a/document/src/vespa/document/fieldset/fieldsetrepo.cpp +++ b/document/src/vespa/document/fieldset/fieldsetrepo.cpp @@ -28,10 +28,12 @@ parseSpecialValues(vespalib::stringref name) return std::make_shared<NoFields>(); } else if ((name.size() == 7) && (name[1] == 'd') && (name[2] == 'o') && (name[3] == 'c') && (name[4] == 'i') && (name[5] == 'd') && (name[6] == ']')) { return std::make_shared<DocIdOnly>(); + } else if (name.size() == 10 && name == DocumentOnly::NAME) { + return std::make_shared<DocumentOnly>(); } else { throw vespalib::IllegalArgumentException( "The only special names (enclosed in '[]') allowed are " - "id, all, none, not '" + name + "'."); + "id, all, none, docid, document; but not '" + name + "'."); } } @@ -109,6 +111,8 @@ FieldSetRepo::serialize(const FieldSet& fieldSet) return NoFields::NAME; case FieldSet::Type::DOCID: return DocIdOnly::NAME; + case FieldSet::Type::DOCUMENT_ONLY: + return DocumentOnly::NAME; default: return ""; } diff --git a/document/src/vespa/document/fieldset/fieldsets.cpp b/document/src/vespa/document/fieldset/fieldsets.cpp index 403e220466c..74dac80879a 100644 --- a/document/src/vespa/document/fieldset/fieldsets.cpp +++ b/document/src/vespa/document/fieldset/fieldsets.cpp @@ -47,6 +47,7 @@ FieldCollection::contains(const FieldSet& fields) const case Type::NONE: case Type::DOCID: return true; + case Type::DOCUMENT_ONLY: case Type::ALL: return false; } @@ -60,6 +61,12 @@ FieldSet::copyFields(Document& dest, const Document& src, const FieldSet& fields if (fields.getType() == Type::ALL) { dest.getFields() = src.getFields(); return; + } else if (fields.getType() == Type::DOCUMENT_ONLY) { + const auto * actual = src.getType().getFieldSet(DocumentOnly::NAME); + if (actual != nullptr) { + copyFields(dest, src, actual->asCollection()); + } + return; } for (Document::const_iterator it(src.begin()), e(src.end()); it != e; ++it) @@ -90,6 +97,15 @@ FieldSet::stripFields(Document& doc, const FieldSet& fieldsToKeep) { doc.clear(); return; + } else if (fieldsToKeep.getType() == Type::DOCUMENT_ONLY) { + const auto * actual = doc.getType().getFieldSet(DocumentOnly::NAME); + if (actual != nullptr) { + return stripFields(doc, actual->asCollection()); + } else { + // XXX - should not happen + doc.clear(); + return; + } } std::vector<const Field*> fieldsToRemove; for (Document::const_iterator it(doc.begin()), e(doc.end()); diff --git a/document/src/vespa/document/fieldset/fieldsets.h b/document/src/vespa/document/fieldset/fieldsets.h index 59cda189018..c92453cc67e 100644 --- a/document/src/vespa/document/fieldset/fieldsets.h +++ b/document/src/vespa/document/fieldset/fieldsets.h @@ -33,6 +33,18 @@ public: Type getType() const override { return Type::DOCID; } }; +class DocumentOnly final : public FieldSet +{ +public: + static constexpr const char * NAME = "[document]"; + bool contains(const FieldSet& fields) const override { + return fields.getType() == Type::DOCUMENT_ONLY + || fields.getType() == Type::DOCID + || fields.getType() == Type::NONE; + } + Type getType() const override { return Type::DOCUMENT_ONLY; } +}; + class FieldCollection : public FieldSet { public: diff --git a/searchcore/src/vespa/searchcore/proton/server/documentretriever.cpp b/searchcore/src/vespa/searchcore/proton/server/documentretriever.cpp index 6285f4ce70f..d3778b4d745 100644 --- a/searchcore/src/vespa/searchcore/proton/server/documentretriever.cpp +++ b/searchcore/src/vespa/searchcore/proton/server/documentretriever.cpp @@ -127,6 +127,7 @@ DocumentRetriever::needFetchFromDocStore(const FieldSet & fieldSet) const { case FieldSet::Type::NONE: case FieldSet::Type::DOCID: return false; + case FieldSet::Type::DOCUMENT_ONLY: case FieldSet::Type::ALL: return ! _areAllFieldsAttributes; case FieldSet::Type::FIELD: { @@ -257,6 +258,14 @@ DocumentRetriever::getPartialDocument(search::DocumentIdT lid, const document::D populate(lid, *doc, set.getFields()); break; } + case FieldSet::Type::DOCUMENT_ONLY: { + const auto * actual = getDocumentType().getFieldSet(document::DocumentOnly::NAME); + if (actual != nullptr) { + const auto &set = actual->asCollection(); + populate(lid, *doc, set.getFields()); + } + break; + } case FieldSet::Type::NONE: case FieldSet::Type::DOCID: break; |