diff options
author | Arne H Juul <arnej@yahooinc.com> | 2021-12-18 00:16:28 +0000 |
---|---|---|
committer | Arne H Juul <arnej@yahooinc.com> | 2022-01-24 12:29:04 +0000 |
commit | 754886cee3a828a55bf69b463d399ffa74bd8e22 (patch) | |
tree | a2408cb502ed9366dc8ceb4adf5ea07604a8400b /searchsummary | |
parent | e66c203626e803f1ddc6a396623772adffba54e0 (diff) |
configurable position rendering
* in summary field writers
Diffstat (limited to 'searchsummary')
6 files changed, 149 insertions, 40 deletions
diff --git a/searchsummary/src/tests/docsummary/positionsdfw_test.cpp b/searchsummary/src/tests/docsummary/positionsdfw_test.cpp index 52a363c9888..b9469ca2102 100644 --- a/searchsummary/src/tests/docsummary/positionsdfw_test.cpp +++ b/searchsummary/src/tests/docsummary/positionsdfw_test.cpp @@ -131,8 +131,7 @@ void checkWritePositionField(Test &test, AttrType &attr, } MyAttributeManager attribute_man(attr); - PositionsDFW::UP writer = - createPositionsDFW(attr.getName().c_str(), &attribute_man); + PositionsDFW::UP writer = PositionsDFW::create(attr.getName().c_str(), &attribute_man, false); ASSERT_TRUE(writer.get()); ResType res_type = RES_JSONSTRING; MyGetDocsumsStateCallback callback; diff --git a/searchsummary/src/vespa/searchsummary/docsummary/docsumconfig.cpp b/searchsummary/src/vespa/searchsummary/docsummary/docsumconfig.cpp index a1bc690e042..380d29ef4b8 100644 --- a/searchsummary/src/vespa/searchsummary/docsummary/docsumconfig.cpp +++ b/searchsummary/src/vespa/searchsummary/docsummary/docsumconfig.cpp @@ -72,19 +72,19 @@ DynamicDocsumConfig::createFieldWriter(const string & fieldName, const string & } else if (overrideName == "absdist") { if (getEnvironment()) { IAttributeManager *am = getEnvironment()->getAttributeManager(); - fieldWriter = createAbsDistanceDFW(argument.c_str(), am); + fieldWriter = AbsDistanceDFW::create(argument.c_str(), am, resultConfig.useV8geoPositions()); rc = fieldWriter.get(); } } else if (overrideName == "positions") { if (getEnvironment()) { IAttributeManager *am = getEnvironment()->getAttributeManager(); - fieldWriter = createPositionsDFW(argument.c_str(), am); + fieldWriter = PositionsDFW::create(argument.c_str(), am, resultConfig.useV8geoPositions()); rc = fieldWriter.get(); } } else if (overrideName == "geopos") { if (getEnvironment()) { IAttributeManager *am = getEnvironment()->getAttributeManager(); - fieldWriter = GeoPositionDFW::create(argument.c_str(), am); + fieldWriter = GeoPositionDFW::create(argument.c_str(), am, resultConfig.useV8geoPositions()); rc = fieldWriter.get(); } } else if (overrideName == "attribute") { diff --git a/searchsummary/src/vespa/searchsummary/docsummary/geoposdfw.cpp b/searchsummary/src/vespa/searchsummary/docsummary/geoposdfw.cpp index 1f73872af6e..cfc492d50ee 100644 --- a/searchsummary/src/vespa/searchsummary/docsummary/geoposdfw.cpp +++ b/searchsummary/src/vespa/searchsummary/docsummary/geoposdfw.cpp @@ -19,14 +19,19 @@ using attribute::IAttributeVector; using attribute::IAttributeContext; using vespalib::Issue; -GeoPositionDFW::GeoPositionDFW(const vespalib::string & attrName) : - AttrDFW(attrName) +GeoPositionDFW::GeoPositionDFW(const vespalib::string & attrName, bool useV8geoPositions) : + AttrDFW(attrName), + _useV8geoPositions(useV8geoPositions) { } namespace { -void fmtZcurve(int64_t zval, vespalib::slime::Inserter &target) -{ +double to_degrees(int32_t microDegrees) { + double d = microDegrees / 1.0e6; + return d; +} + +void fmtZcurve(int64_t zval, vespalib::slime::Inserter &target, bool useV8geoPositions) { int32_t docx = 0; int32_t docy = 0; vespalib::geo::ZCurve::decode(zval, &docx, &docy); @@ -34,8 +39,15 @@ void fmtZcurve(int64_t zval, vespalib::slime::Inserter &target) LOG(spam, "skipping empty zcurve value"); } else { vespalib::slime::Cursor &obj = target.insertObject(); - obj.setLong("y", docy); - obj.setLong("x", docx); + if (useV8geoPositions) { + double degrees_ns = to_degrees(docy); + double degrees_ew = to_degrees(docx); + obj.setDouble("lat", degrees_ns); + obj.setDouble("lng", degrees_ew); + } else { + obj.setLong("y", docy); + obj.setLong("x", docx); + } } } @@ -62,7 +74,7 @@ GeoPositionDFW::insertField(uint32_t docid, GetDocsumsState * dsState, ResType, Cursor &elem = arr.addObject(); int64_t pos = elements[i].getValue(); ObjectSymbolInserter obj(elem, isym); - fmtZcurve(pos, obj); + fmtZcurve(pos, obj, _useV8geoPositions); elem.setLong(wsym, elements[i].getWeight()); } } else { @@ -76,18 +88,19 @@ GeoPositionDFW::insertField(uint32_t docid, GetDocsumsState * dsState, ResType, for (uint32_t i = 0; i < numValues; i++) { int64_t pos = elements[i]; ArrayInserter obj(arr); - fmtZcurve(pos, obj); + fmtZcurve(pos, obj, _useV8geoPositions); } } } else { int64_t pos = attribute.getInt(docid); - fmtZcurve(pos, target); + fmtZcurve(pos, target, _useV8geoPositions); } } GeoPositionDFW::UP GeoPositionDFW::create(const char *attribute_name, - IAttributeManager *attribute_manager) + IAttributeManager *attribute_manager, + bool useV8geoPositions) { GeoPositionDFW::UP ret; if (attribute_manager != nullptr) { @@ -106,8 +119,7 @@ GeoPositionDFW::create(const char *attribute_name, return ret; } } - ret.reset(new GeoPositionDFW(attribute_name)); - return ret; + return std::make_unique<GeoPositionDFW>(attribute_name, useV8geoPositions); } } diff --git a/searchsummary/src/vespa/searchsummary/docsummary/geoposdfw.h b/searchsummary/src/vespa/searchsummary/docsummary/geoposdfw.h index 020e864d902..5dcee853304 100644 --- a/searchsummary/src/vespa/searchsummary/docsummary/geoposdfw.h +++ b/searchsummary/src/vespa/searchsummary/docsummary/geoposdfw.h @@ -11,11 +11,13 @@ namespace search::docsummary { **/ class GeoPositionDFW : public AttrDFW { +private: + bool _useV8geoPositions; public: typedef std::unique_ptr<GeoPositionDFW> UP; - GeoPositionDFW(const vespalib::string & attrName); + GeoPositionDFW(const vespalib::string & attrName, bool useV8geoPositions); void insertField(uint32_t docid, GetDocsumsState *state, ResType type, vespalib::slime::Inserter &target) override; - static UP create(const char *attribute_name, IAttributeManager *attribute_manager); + static UP create(const char *attribute_name, IAttributeManager *attribute_manager, bool useV8geoPositions); }; } diff --git a/searchsummary/src/vespa/searchsummary/docsummary/positionsdfw.cpp b/searchsummary/src/vespa/searchsummary/docsummary/positionsdfw.cpp index ce14069a135..c46988de0d2 100644 --- a/searchsummary/src/vespa/searchsummary/docsummary/positionsdfw.cpp +++ b/searchsummary/src/vespa/searchsummary/docsummary/positionsdfw.cpp @@ -4,6 +4,7 @@ #include "docsumstate.h" #include <vespa/searchlib/attribute/iattributemanager.h> #include <vespa/searchcommon/attribute/attributecontent.h> +#include <vespa/searchlib/common/geo_gcd.h> #include <vespa/searchlib/common/location.h> #include <vespa/vespalib/stllike/asciistream.h> #include <vespa/vespalib/data/slime/cursor.h> @@ -16,11 +17,21 @@ LOG_SETUP(".searchlib.docsummary.positionsdfw"); namespace search::docsummary { +namespace { + +double to_degrees(int32_t microDegrees) { + double d = microDegrees / 1.0e6; + return d; +} + +} + using search::attribute::IAttributeContext; using search::attribute::IAttributeVector; using search::attribute::BasicType; using search::attribute::IntegerContent; using search::common::Location; +using search::common::GeoGcd; LocationAttrDFW::AllLocations LocationAttrDFW::getAllLocations(GetDocsumsState *state) @@ -50,10 +61,40 @@ LocationAttrDFW::getAllLocations(GetDocsumsState *state) return retval; } -AbsDistanceDFW::AbsDistanceDFW(const vespalib::string & attrName) : - LocationAttrDFW(attrName) +AbsDistanceDFW::AbsDistanceDFW(const vespalib::string & attrName, bool useV8geoPositions) : + LocationAttrDFW(attrName), + _useV8geoPositions(useV8geoPositions) { } +double +AbsDistanceDFW::kmMinDistance(uint32_t docid, GetDocsumsState *state, + const std::vector<const GeoLoc *> &locations) +{ + double best = std::numeric_limits<double>::max(); + const auto& attribute = get_attribute(*state); + for (auto location : locations) { + double lat = to_degrees(location->point.y); + double lng = to_degrees(location->point.x); + GeoGcd point{lat, lng}; + int32_t docx = 0; + int32_t docy = 0; + IntegerContent pos; + pos.fill(attribute, docid); + uint32_t numValues = pos.size(); + for (uint32_t i = 0; i < numValues; i++) { + int64_t docxy(pos[i]); + vespalib::geo::ZCurve::decode(docxy, &docx, &docy); + lat = to_degrees(docy); + lng = to_degrees(docx); + double dist = point.km_great_circle_distance(lat, lng); + if (dist < best) { + best = dist; + } + } + } + return best; +} + uint64_t AbsDistanceDFW::findMinDistance(uint32_t docid, GetDocsumsState *state, const std::vector<const GeoLoc *> &locations) @@ -105,8 +146,9 @@ AbsDistanceDFW::insertField(uint32_t docid, GetDocsumsState *state, ResType type //-------------------------------------------------------------------------- -PositionsDFW::PositionsDFW(const vespalib::string & attrName) : - AttrDFW(attrName) +PositionsDFW::PositionsDFW(const vespalib::string & attrName, bool useV8geoPositions) : + AttrDFW(attrName), + _useV8geoPositions(useV8geoPositions) { } @@ -127,10 +169,8 @@ insertPos(int64_t docxy, vespalib::slime::Inserter &target) obj.setLong("y", docy); obj.setLong("x", docx); - double degrees_ns = docy; - degrees_ns /= 1000000.0; - double degrees_ew = docx; - degrees_ew /= 1000000.0; + double degrees_ns = to_degrees(docy); + double degrees_ew = to_degrees(docx); vespalib::asciistream latlong; latlong << vespalib::FloatSpec::fixed; @@ -176,19 +216,70 @@ void checkExpected(ResType type) { LOG(error, "Unexpected summary field type %s", ResultConfig::GetResTypeName(type)); } +void insertPosV8(int64_t docxy, vespalib::slime::Inserter &target) { + int32_t docx = 0; + int32_t docy = 0; + vespalib::geo::ZCurve::decode(docxy, &docx, &docy); + if (docx == 0 && docy == INT_MIN) { + LOG(spam, "skipping empty zcurve value"); + return; + } + double degrees_ns = to_degrees(docy); + double degrees_ew = to_degrees(docx); + vespalib::slime::Cursor &obj = target.insertObject(); + obj.setDouble("lat", degrees_ns); + obj.setDouble("lng", degrees_ew); + vespalib::asciistream latlong; + latlong << vespalib::FloatSpec::fixed; + if (degrees_ns < 0) { + latlong << "S" << (-degrees_ns); + } else { + latlong << "N" << degrees_ns; + } + latlong << ";"; + if (degrees_ew < 0) { + latlong << "W" << (-degrees_ew); + } else { + latlong << "E" << degrees_ew; + } + obj.setString("latlong", vespalib::Memory(latlong.str())); +} + + +void insertV8FromAttr(const attribute::IAttributeVector &attribute, uint32_t docid, vespalib::slime::Inserter &target) { + IntegerContent pos; + pos.fill(attribute, docid); + uint32_t numValues = pos.size(); + LOG(debug, "docid=%d, numValues=%d", docid, numValues); + if (numValues > 0) { + if (attribute.getCollectionType() == attribute::CollectionType::SINGLE) { + insertPosV8(pos[0], target); + } else { + vespalib::slime::Cursor &arr = target.insertArray(); + for (uint32_t i = 0; i < numValues; i++) { + vespalib::slime::ArrayInserter ai(arr); + insertPosV8(pos[i], ai); + } + } + } +} + } // namespace void PositionsDFW::insertField(uint32_t docid, GetDocsumsState * dsState, ResType type, vespalib::slime::Inserter &target) { checkExpected(type); - insertFromAttr(get_attribute(*dsState), docid, target); + if (_useV8geoPositions) { + insertV8FromAttr(get_attribute(*dsState), docid, target); + } else { + insertFromAttr(get_attribute(*dsState), docid, target); + } } //-------------------------------------------------------------------------- -PositionsDFW::UP createPositionsDFW(const char *attribute_name, IAttributeManager *attribute_manager) -{ +PositionsDFW::UP PositionsDFW::create(const char *attribute_name, IAttributeManager *attribute_manager, bool useV8geoPositions) { PositionsDFW::UP ret; if (attribute_manager != nullptr) { if (!attribute_name) { @@ -206,11 +297,10 @@ PositionsDFW::UP createPositionsDFW(const char *attribute_name, IAttributeManage return ret; } } - return std::make_unique<PositionsDFW>(attribute_name); + return std::make_unique<PositionsDFW>(attribute_name, useV8geoPositions); } -AbsDistanceDFW::UP createAbsDistanceDFW(const char *attribute_name, IAttributeManager *attribute_manager) -{ +AbsDistanceDFW::UP AbsDistanceDFW::create(const char *attribute_name, IAttributeManager *attribute_manager, bool useV8geoPositions) { AbsDistanceDFW::UP ret; if (attribute_manager != nullptr) { if (!attribute_name) { @@ -228,7 +318,7 @@ AbsDistanceDFW::UP createAbsDistanceDFW(const char *attribute_name, IAttributeMa return ret; } } - return std::make_unique<AbsDistanceDFW>(attribute_name); + return std::make_unique<AbsDistanceDFW>(attribute_name, useV8geoPositions); } } diff --git a/searchsummary/src/vespa/searchsummary/docsummary/positionsdfw.h b/searchsummary/src/vespa/searchsummary/docsummary/positionsdfw.h index eeab2f33b5b..727f6393e2e 100644 --- a/searchsummary/src/vespa/searchsummary/docsummary/positionsdfw.h +++ b/searchsummary/src/vespa/searchsummary/docsummary/positionsdfw.h @@ -3,6 +3,7 @@ #pragma once #include "attributedfw.h" +#include "resultconfig.h" #include <vespa/searchlib/common/geo_location_spec.h> namespace search::docsummary { @@ -35,30 +36,35 @@ public: class AbsDistanceDFW : public LocationAttrDFW { private: + bool _useV8geoPositions; + double kmMinDistance(uint32_t docid, GetDocsumsState *state, + const std::vector<const GeoLoc *> &locations); uint64_t findMinDistance(uint32_t docid, GetDocsumsState *state, const std::vector<const GeoLoc *> &locations); public: - AbsDistanceDFW(const vespalib::string & attrName); + AbsDistanceDFW(const vespalib::string & attrName, bool useV8geoPositions); bool IsGenerated() const override { return true; } void insertField(uint32_t docid, GetDocsumsState *state, ResType type, vespalib::slime::Inserter &target) override; + + static UP create(const char *attribute_name, IAttributeManager *index_man, bool useV8geoPositions); + }; //-------------------------------------------------------------------------- class PositionsDFW : public AttrDFW { +private: + bool _useV8geoPositions; public: typedef std::unique_ptr<PositionsDFW> UP; - - PositionsDFW(const vespalib::string & attrName); - + PositionsDFW(const vespalib::string & attrName, bool useV8geoPositions); bool IsGenerated() const override { return true; } void insertField(uint32_t docid, GetDocsumsState *state, ResType type, vespalib::slime::Inserter &target) override; + static UP create(const char *attribute_name, IAttributeManager *index_man, bool useV8geoPositions); }; -PositionsDFW::UP createPositionsDFW(const char *attribute_name, IAttributeManager *index_man); -AbsDistanceDFW::UP createAbsDistanceDFW(const char *attribute_name, IAttributeManager *index_man); } |