summaryrefslogtreecommitdiffstats
path: root/searchsummary/src/vespa/searchsummary/docsummary/docsumwriter.cpp
blob: b4b663718bdc140a5b8486326448a20a7043ecaf (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.

#include "docsumwriter.h"
#include "docsumstate.h"
#include "docsum_field_writer_state.h"
#include "i_docsum_store_document.h"
#include "keywordextractor.h"
#include <vespa/document/fieldvalue/fieldvalue.h>
#include <vespa/searchlib/attribute/iattributemanager.h>
#include <vespa/vespalib/util/issue.h>
#include <vespa/vespalib/data/slime/inserter.h>

#include <vespa/log/log.h>
LOG_SETUP(".searchlib.docsummary.docsumwriter");

using vespalib::Issue;
using vespalib::Memory;
using vespalib::slime::ObjectInserter;

namespace search::docsummary {

DynamicDocsumWriter::ResolveClassInfo
DynamicDocsumWriter::resolveClassInfo(vespalib::stringref outputClassName) const
{
    DynamicDocsumWriter::ResolveClassInfo rci = resolveOutputClass(outputClassName);
    return rci;
}

DynamicDocsumWriter::ResolveClassInfo
DynamicDocsumWriter::resolveOutputClass(vespalib::stringref summaryClass) const
{
    DynamicDocsumWriter::ResolveClassInfo result;
    auto id = _resultConfig->LookupResultClassId(summaryClass);

    const ResultClass *oC = (id != ResultConfig::NoClassID()) ? _resultConfig->LookupResultClass(id) : nullptr;
    if (oC == nullptr) {
        Issue::report("Illegal docsum class requested: %s, using empty docsum for documents",
                      vespalib::string(summaryClass).c_str());
    } else {
        const ResultClass::DynamicInfo &rcInfo = oC->getDynamicInfo();
        if (rcInfo._generateCnt == oC->GetNumEntries()) {
            LOG_ASSERT(rcInfo._overrideCnt == rcInfo._generateCnt);
            result.allGenerated = true;
        }
    }
    result.outputClass = oC;
    return result;
}

void
DynamicDocsumWriter::insertDocsum(const ResolveClassInfo & rci, uint32_t docid, GetDocsumsState& state,
                                  IDocsumStore *docinfos, Inserter& topInserter)
{
    if (rci.outputClass == nullptr) {
        // Use empty docsum when illegal docsum class has been requested
        return;
    }
    if (rci.allGenerated) {
        // generate docsum entry on-the-fly
        vespalib::slime::Cursor & docsum = topInserter.insertObject();
        for (uint32_t i = 0; i < rci.outputClass->GetNumEntries(); ++i) {
            const ResConfigEntry *resCfg = rci.outputClass->GetEntry(i);
            const DocsumFieldWriter *writer = resCfg->_docsum_field_writer.get();
            if (state._args.needField(resCfg->_name) && ! writer->isDefaultValue(docid, state)) {
                const Memory field_name(resCfg->_name.data(), resCfg->_name.size());
                ObjectInserter inserter(docsum, field_name);
                writer->insertField(docid, nullptr, state, inserter);
            }
        }
    } else {
        // look up docsum entry
        auto doc = docinfos->getMappedDocsum(docid);
        if (!doc) {
            return; // Use empty docsum when document is gone
        }
        // insert docsum blob
        vespalib::slime::Cursor & docsum = topInserter.insertObject();
        for (uint32_t i = 0; i < rci.outputClass->GetNumEntries(); ++i) {
            const ResConfigEntry *outCfg = rci.outputClass->GetEntry(i);
            if (!state._args.needField(outCfg->_name)) {
                continue;
            }
            const DocsumFieldWriter *writer = outCfg->_docsum_field_writer.get();
            const Memory field_name(outCfg->_name.data(), outCfg->_name.size());
            ObjectInserter inserter(docsum, field_name);
            if (writer != nullptr) {
                if (! writer->isDefaultValue(docid, state)) {
                    writer->insertField(docid, doc.get(), state, inserter);
                }
            } else {
                if (doc) {
                    doc->insert_summary_field(outCfg->_name, inserter);
                }
            }
        }
    }
}

DynamicDocsumWriter::DynamicDocsumWriter(std::unique_ptr<ResultConfig> config, std::unique_ptr<KeywordExtractor> extractor)
    : _resultConfig(std::move(config)),
      _keywordExtractor(std::move(extractor))
{
}


DynamicDocsumWriter::~DynamicDocsumWriter() = default;

void
DynamicDocsumWriter::InitState(const IAttributeManager & attrMan, GetDocsumsState& state, const ResolveClassInfo& rci)
{
    state._kwExtractor = _keywordExtractor.get();
    state._attrCtx = attrMan.createContext();
    auto result_class = rci.outputClass;
    if (result_class == nullptr) {
        return;
    }
    size_t num_entries = result_class->GetNumEntries();
    state._attributes.resize(num_entries);
    state._fieldWriterStates.resize(result_class->get_num_field_writer_states());
    for (size_t i(0); i < num_entries; i++) {
        const DocsumFieldWriter *fw = result_class->GetEntry(i)->_docsum_field_writer.get();
        if (fw) {
            const vespalib::string & attributeName = fw->getAttributeName();
            if (!attributeName.empty()) {
                state._attributes[i] = state._attrCtx->getAttribute(attributeName);
            }
        }
    }
}

}