rocksdb::Status Geo::SearchStore()

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();
}