// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. #include "juniperdfw.h" #include "docsumstate.h" #include "i_docsum_store_document.h" #include "i_juniper_converter.h" #include "juniper_query_adapter.h" #include #include #include #include #include #include LOG_SETUP(".searchlib.docsummary.dynamicteaserdfw"); namespace search::docsummary { JuniperDFW::JuniperDFW(const juniper::Juniper * juniper) : _input_field_name(), _juniperConfig(), _juniper(juniper) { } JuniperDFW::~JuniperDFW() = default; bool JuniperDFW::Init( const char *fieldName, const vespalib::string& inputField) { bool rc = true; _juniperConfig = _juniper->CreateConfig(fieldName); if ( ! _juniperConfig) { LOG(warning, "could not create juniper config for field '%s'", fieldName); rc = false; } _input_field_name = inputField; return rc; } bool JuniperTeaserDFW::Init( const char *fieldName, const vespalib::string& inputField) { return JuniperDFW::Init(fieldName, inputField); } void DynamicTeaserDFW::insert_juniper_field(uint32_t docid, vespalib::stringref input, GetDocsumsState& state, vespalib::slime::Inserter& inserter) const { if (!state._dynteaser._query) { JuniperQueryAdapter iq(state._kwExtractor, state._args.getStackDump(), &state._args.highlightTerms()); state._dynteaser._query = _juniper->CreateQueryHandle(iq, nullptr); } LOG(debug, "makeDynamicTeaser: docid (%d)", docid); std::unique_ptr result; if (state._dynteaser._query != nullptr) { if (LOG_WOULD_LOG(spam)) { std::ostringstream hexDump; hexDump << vespalib::HexDump(input.data(), input.length()); LOG(spam, "makeDynamicTeaser: docid=%d, input='%s', hexdump:\n%s", docid, std::string(input.data(), input.length()).c_str(), hexDump.str().c_str()); } auto langid = static_cast(-1); result = juniper::Analyse(*_juniperConfig, *state._dynteaser._query, input.data(), input.length(), docid, langid); } juniper::Summary *teaser = result ? juniper::GetTeaser(*result, _juniperConfig.get()) : nullptr; if (LOG_WOULD_LOG(debug)) { std::ostringstream hexDump; if (teaser != nullptr) { hexDump << vespalib::HexDump(teaser->Text(), teaser->Length()); } LOG(debug, "makeDynamicTeaser: docid=%d, teaser='%s', hexdump:\n%s", docid, (teaser != nullptr ? std::string(teaser->Text(), teaser->Length()).c_str() : "nullptr"), hexDump.str().c_str()); } if (teaser != nullptr) { inserter.insertString({teaser->Text(), teaser->Length()}); } else { inserter.insertString({}); } } namespace { class JuniperConverter : public IJuniperConverter { const DynamicTeaserDFW& _writer; uint32_t _doc_id; GetDocsumsState& _state; public: JuniperConverter(const DynamicTeaserDFW& writer, uint32_t doc_id, GetDocsumsState& state); ~JuniperConverter() override; void insert_juniper_field(vespalib::stringref input, vespalib::slime::Inserter& inserter) override; }; JuniperConverter::JuniperConverter(const DynamicTeaserDFW& writer, uint32_t doc_id, GetDocsumsState& state) : IJuniperConverter(), _writer(writer), _doc_id(doc_id), _state(state) { } JuniperConverter::~JuniperConverter() = default; void JuniperConverter::insert_juniper_field(vespalib::stringref input, vespalib::slime::Inserter& inserter) { _writer.insert_juniper_field(_doc_id, input, _state, inserter); } } void DynamicTeaserDFW::insertField(uint32_t docid, const IDocsumStoreDocument* doc, GetDocsumsState *state, ResType, vespalib::slime::Inserter &target) const { if (doc != nullptr) { JuniperConverter converter(*this, docid, *state); doc->insert_juniper_field(_input_field_name, target, converter); } } }