in src/types/redis_geo.cc [114:185]
rocksdb::Status Geo::SearchStore(engine::Context &ctx, const Slice &user_key, GeoShape geo_shape,
OriginPointType point_type, std::string &member, int count, DistanceSort sort,
const std::string &store_key, bool store_distance, double unit_conversion,
std::vector<GeoPoint> *geo_points) {
if (point_type == kMember) {
GeoPoint geo_point;
auto s = Get(ctx, user_key, member, &geo_point);
// store key is not empty, try to remove it before returning.
if (!s.ok() && s.IsNotFound() && !store_key.empty()) {
auto del_s = ZSet::Del(ctx, store_key);
if (!del_s.ok()) return del_s;
}
if (!s.ok()) return s.IsNotFound() ? rocksdb::Status::OK() : s;
geo_shape.xy[0] = geo_point.longitude;
geo_shape.xy[1] = geo_point.latitude;
}
std::string ns_key = AppendNamespacePrefix(user_key);
ZSetMetadata metadata(false);
rocksdb::Status s = ZSet::GetMetadata(ctx, ns_key, &metadata);
// store key is not empty, try to remove it before returning.
if (!s.ok() && s.IsNotFound() && !store_key.empty()) {
auto del_s = ZSet::Del(ctx, store_key);
if (!del_s.ok()) return del_s;
}
if (!s.ok()) return s.IsNotFound() ? rocksdb::Status::OK() : s;
// Get neighbor geohash boxes for radius search
GeoHashRadius georadius = GeoHashHelper::GetAreasByShapeWGS84(geo_shape);
// Get zset for all matching points
membersOfAllNeighbors(ctx, user_key, georadius, geo_shape, geo_points);
// if no matching results, give empty reply
if (geo_points->empty()) {
// store key is not empty, try to remove it before returning.
if (!store_key.empty()) {
auto del_s = ZSet::Del(ctx, store_key);
if (!del_s.ok()) return del_s;
}
return rocksdb::Status::OK();
}
// process [optional] sorting
if (sort == kSortASC) {
std::sort(geo_points->begin(), geo_points->end(), sortGeoPointASC);
} else if (sort == kSortDESC) {
std::sort(geo_points->begin(), geo_points->end(), sortGeoPointDESC);
}
// storing
if (!store_key.empty()) {
auto result_length = static_cast<int64_t>(geo_points->size());
int64_t returned_items_count = (count == 0 || result_length < count) ? result_length : count;
if (returned_items_count == 0) {
auto s = ZSet::Del(ctx, user_key);
if (!s.ok()) return s;
} else {
std::vector<MemberScore> member_scores;
for (const auto &geo_point : *geo_points) {
if (returned_items_count-- <= 0) {
break;
}
double score = store_distance ? geo_point.dist / unit_conversion : geo_point.score;
member_scores.emplace_back(MemberScore{geo_point.member, score});
}
ZSet::Overwrite(ctx, store_key, member_scores);
}
}
return rocksdb::Status::OK();
}