diff --git a/src/search_local/index_read/component.cc b/src/search_local/index_read/component.cc index baa9035..2ef43ea 100644 --- a/src/search_local/index_read/component.cc +++ b/src/search_local/index_read/component.cc @@ -25,6 +25,7 @@ #include "query/range_query_parser.h" #include "query/match_query_parser.h" #include "query/term_query_parser.h" +#include "query/geo_shape_parser.h" #include using namespace std; @@ -230,6 +231,8 @@ int Component::GetQueryWord(uint32_t &m_has_gis, string &err_msg){ query_parser = new MatchQueryParser(m_appid, m_query["match"]); } else if(m_query.isMember("term")){ query_parser = new TermQueryParser(m_appid, m_query["term"]); + } else if(m_query.isMember("geo_shape")){ + query_parser = new GeoShapeParser(m_appid, m_query["geo_shape"]); } query_parser_res = new QueryParserRes(); int ret = query_parser->ParseContent(query_parser_res); diff --git a/src/search_local/index_read/query/geo_shape_parser.cc b/src/search_local/index_read/query/geo_shape_parser.cc new file mode 100644 index 0000000..283c78b --- /dev/null +++ b/src/search_local/index_read/query/geo_shape_parser.cc @@ -0,0 +1,141 @@ +#include "geo_shape_parser.h" +#include "../db_manager.h" +#include + +const char* const POINTS ="points"; +const int GEO_PRECISION = 6; + +GeoShapeParser::GeoShapeParser(uint32_t a, Json::Value& v) +:appid(a),value(v) +{ + +} + +GeoShapeParser::~GeoShapeParser(){ + +} + +vector GeoShapeParser::splitDouble(const string& src, string separate_character) +{ + vector strs; + + //分割字符串的长度,这样就可以支持如“,,”多字符串的分隔符 + int separate_characterLen = separate_character.size(); + int lastPosition = 0, index = -1; + string str; + double pos = 0; + while (-1 != (index = src.find(separate_character, lastPosition))) + { + if (src.substr(lastPosition, index - lastPosition) != " ") { + str = src.substr(lastPosition, index - lastPosition); + pos = atof(str.c_str()); + strs.push_back(pos); + } + lastPosition = index + separate_characterLen; + } + string lastString = src.substr(lastPosition);//截取最后一个分隔符后的内容 + if (!lastString.empty() && lastString != " "){ + pos = atof(lastString.c_str()); + strs.push_back(pos);//如果最后一个分隔符后还有内容就入队 + } + return strs; +} + +void GeoShapeParser::SetErrMsg(QueryParserRes* query_parser_res, string err_msg){ + log_error(err_msg.c_str()); + query_parser_res->ErrMsg() = err_msg; +} + +int GeoShapeParser::ParseContent(QueryParserRes* query_parser_res){ + Json::Value::Members member = value.getMemberNames(); + Json::Value::Members::iterator iter = member.begin(); + if(iter == member.end()){ // 一个geo_shape下只对应一个字段 + SetErrMsg(query_parser_res, "GeoShapeParser format error, content is null."); + return -RT_PARSE_CONTENT_ERROR; + } + set lat_arr; + set lon_arr; + string fieldname = *iter; + Json::Value field_value = value[fieldname]; + if(field_value.isMember(POINTS)){ + Json::Value points = field_value[POINTS]; + if(points.isArray()){ + for(int i = 0; i < (int)points.size(); i++){ + double lat; + double lon; + Json::Value geo_value = points[i]; + if(geo_value.isString()){ + string geo_str = geo_value.asString(); + vector res = splitDouble(geo_str, ","); + if(res.size() >= 2){ + lat = res[0]; + lon = res[1]; + } else { + SetErrMsg(query_parser_res, "GeoShapeParser format error."); + return -RT_PARSE_CONTENT_ERROR; + } + } else if (geo_value.isArray()){ + if(geo_value.size() >= 2){ + if(geo_value[0].isDouble()){ + lon = geo_value[0].asDouble(); + } + if(geo_value[1].isDouble()){ + lat = geo_value[1].asDouble(); + } + } else { + SetErrMsg(query_parser_res, "GeoShapeParser format error."); + return -RT_PARSE_CONTENT_ERROR; + } + } else if (geo_value.isObject()){ + if(geo_value.isMember("lat") && geo_value["lat"].isDouble()){ + lat = geo_value["lat"].asDouble(); + } else { + SetErrMsg(query_parser_res, "GeoShapeParser lat format error."); + return -RT_PARSE_CONTENT_ERROR; + } + if(geo_value.isMember("lon") && geo_value["lon"].isDouble()){ + lon = geo_value["lon"].asDouble(); + } else { + SetErrMsg(query_parser_res, "GeoShapeParser lon format error."); + return -RT_PARSE_CONTENT_ERROR; + } + } else { + SetErrMsg(query_parser_res, "GeoShapeParser error, value is not string/array/object."); + return -RT_PARSE_CONTENT_ERROR; + } + lat_arr.insert(lat); + lon_arr.insert(lon); + } + } else { + SetErrMsg(query_parser_res, "GeoShapeParser error, points is not a array."); + return -RT_PARSE_CONTENT_ERROR; + } + } else { + SetErrMsg(query_parser_res, "GeoShapeParser error, no points content provide."); + return -RT_PARSE_CONTENT_ERROR; + } + if(lon_arr.size() > 0 && lat_arr.size() > 0){ + vector gisCode = GetArroundGeoHash(*lon_arr.rbegin(), *lon_arr.begin(), *lat_arr.rbegin(), *lat_arr.begin(), GEO_PRECISION); + if(gisCode.size() > 0){ + vector fieldInfos; + uint32_t segment_tag = 0; + FieldInfo fieldInfo; + uint32_t field = DBManager::Instance()->GetWordField(segment_tag, appid, fieldname, fieldInfo); + if (field != 0 && segment_tag == 0) { + query_parser_res->HasGis() = 1; + for (size_t index = 0; index < gisCode.size(); index++) { + FieldInfo info; + info.field = fieldInfo.field; + info.field_type = fieldInfo.field_type; + info.segment_tag = fieldInfo.segment_tag; + info.word = gisCode[index]; + fieldInfos.push_back(info); + } + } + if (fieldInfos.size() != 0) { + query_parser_res->FieldKeysMap().insert(make_pair(fieldInfo.field, fieldInfos)); + } + } + } + return 0; +} \ No newline at end of file diff --git a/src/search_local/index_read/query/geo_shape_parser.h b/src/search_local/index_read/query/geo_shape_parser.h new file mode 100644 index 0000000..14ad291 --- /dev/null +++ b/src/search_local/index_read/query/geo_shape_parser.h @@ -0,0 +1,43 @@ +/* + * ===================================================================================== + * + * Filename: geo_shape_parser.h + * + * Description: geo_shape_parser class definition. + * + * Version: 1.0 + * Created: 08/05/2021 + * Revision: none + * Compiler: gcc + * + * Author: zhulin, shzhulin3@jd.com + * Company: JD.com, Inc. + * + * ===================================================================================== + */ + +#ifndef __GEO_SHAPE_PARSER_H__ +#define __GEO_SHAPE_PARSER_H__ +#include "query_parser.h" +#include "json/json.h" +#include "geohash.h" + +class GeoShapeParser : public QueryParser +{ +public: + GeoShapeParser(uint32_t a, Json::Value& v); + ~GeoShapeParser(); + int ParseContent(QueryParserRes* query_parser_res); + +private: + void SetErrMsg(QueryParserRes* query_parser_res, string err_msg); + vector splitDouble(const string& src, string separate_character); + +private: + uint32_t appid; + Json::Value value; + GeoPoint geo; + double distance; +}; + +#endif \ No newline at end of file