/* * Try to split the range to multiple ranges based on the hash key. * * e.g., for the following range: * * min: 123456789 * max: 125678912 * * when the hash key length is 3, we want to split the range to: * * 1 * min: 123456789 * max: 123999999 * * 2 * min: 124000000 * max: 124999999 * * 3 * min: 125000000 * max: 125678912 * * For this range: * * min: -125678912 * max: -123456789 * * we want: * * 1 * min: -125678912 * max: -125000000 * * 2 * min: -124999999 * max: -124000000 * * 3 * min: -123999999 * max: -123456789 */ public IReadOnlyList <GeohashRange> TrySplit(int hashKeyLength) { var result = new List <GeohashRange>(); var minHashKey = S2Manager.GenerateHashKey(RangeMin, hashKeyLength); var maxHashKey = S2Manager.GenerateHashKey(RangeMax, hashKeyLength); var denominator = (ulong)Math.Pow(10, RangeMin.ToString(CultureInfo.InvariantCulture).Length - minHashKey.ToString(CultureInfo.InvariantCulture).Length); if (minHashKey == maxHashKey) { result.Add(this); } else { for (var l = minHashKey; l <= maxHashKey; l++) { if (l > 0) { result.Add(new GeohashRange(l == minHashKey ? RangeMin : l * denominator, l == maxHashKey ? RangeMax : (l + 1) * denominator - 1)); } else { result.Add(new GeohashRange(l == minHashKey ? RangeMin : (l - 1) * denominator + 1, l == maxHashKey ? RangeMax : l * denominator)); } } } return(result); }
public async Task <GetPointResult> GetPointAsync(GetPointRequest getPointRequest, CancellationToken cancellationToken = default(CancellationToken)) { if (getPointRequest == null) { throw new ArgumentNullException("getPointRequest"); } var geohash = S2Manager.GenerateGeohash(getPointRequest.GeoPoint); var hashKey = S2Manager.GenerateHashKey(geohash, _config.HashKeyLength); var getItemRequest = getPointRequest.GetItemRequest; getItemRequest.TableName = _config.TableName; var hashKeyValue = new AttributeValue { N = hashKey.ToString(CultureInfo.InvariantCulture) }; getItemRequest.Key[_config.HashKeyAttributeName] = hashKeyValue; getItemRequest.Key[_config.RangeKeyAttributeName] = getPointRequest.RangeKeyValue; GetItemResponse getItemResult = await _config.DynamoDBClient.GetItemAsync(getItemRequest, cancellationToken).ConfigureAwait(false); var getPointResult = new GetPointResult(getItemResult); return(getPointResult); }
public async Task <UpdatePointResult> UpdatePointAsync(UpdatePointRequest updatePointRequest, CancellationToken cancellationToken = default(CancellationToken)) { if (updatePointRequest == null) { throw new ArgumentNullException("updatePointRequest"); } var geohash = S2Manager.GenerateGeohash(updatePointRequest.GeoPoint); var hashKey = S2Manager.GenerateHashKey(geohash, _config.HashKeyLength); var updateItemRequest = updatePointRequest.UpdateItemRequest; updateItemRequest.TableName = _config.TableName; var hashKeyValue = new AttributeValue { N = hashKey.ToString(CultureInfo.InvariantCulture) }; updateItemRequest.Key[_config.HashKeyAttributeName] = hashKeyValue; updateItemRequest.Key[_config.RangeKeyAttributeName] = updatePointRequest.RangeKeyValue; // Geohash and geoJson cannot be updated. updateItemRequest.AttributeUpdates.Remove(_config.GeohashAttributeName); updateItemRequest.AttributeUpdates.Remove(_config.GeoJsonAttributeName); UpdateItemResponse updateItemResult = await _config.DynamoDBClient.UpdateItemAsync(updateItemRequest, cancellationToken).ConfigureAwait(false); var updatePointResult = new UpdatePointResult(updateItemResult); return(updatePointResult); }
public async Task <QueryRectangleResult> QueryRectangleAsync(QueryRectangleRequest queryRectangleRequest, CancellationToken cancellationToken = default(CancellationToken)) { if (queryRectangleRequest == null) { throw new ArgumentNullException("queryRectangleRequest"); } var latLngRect = S2Util.GetBoundingLatLngRect(queryRectangleRequest); var cellUnion = S2Manager.FindCellIds(latLngRect); var ranges = MergeCells(cellUnion); var result = await DispatchQueries(ranges, queryRectangleRequest, cancellationToken).ConfigureAwait(false); return(new QueryRectangleResult(result)); }
public async Task <PutPointResult> PutPointAsync(PutPointRequest putPointRequest, CancellationToken cancellationToken = default(CancellationToken)) { if (putPointRequest == null) { throw new ArgumentNullException("putPointRequest"); } var geohash = S2Manager.GenerateGeohash(putPointRequest.FromGeoPoint); var rangeHash = S2Manager.GenerateGeohash(putPointRequest.ToGeoPoint); var hashKey = S2Manager.GenerateHashKey(geohash, _config.HashKeyLength); var geoJson = GeoJsonMapper.StringFromGeoObject(putPointRequest.FromGeoPoint); var putItemRequest = putPointRequest.PutItemRequest; putItemRequest.TableName = _config.TableName; var hashKeyValue = new AttributeValue { N = hashKey.ToString(CultureInfo.InvariantCulture) }; putItemRequest.Item[_config.HashKeyAttributeName] = hashKeyValue; putItemRequest.Item[_config.RangeKeyAttributeName] = new AttributeValue { S = rangeHash.ToString(CultureInfo.InvariantCulture) }; var geohashValue = new AttributeValue { N = geohash.ToString(CultureInfo.InvariantCulture) }; putItemRequest.Item[_config.GeohashAttributeName] = geohashValue; var geoJsonValue = new AttributeValue { S = geoJson }; putItemRequest.Item[_config.GeoJsonAttributeName] = geoJsonValue; PutItemResponse putItemResult = await _config.DynamoDBClient.PutItemAsync(putItemRequest, cancellationToken).ConfigureAwait(false); var putPointResult = new PutPointResult(putItemResult); return(putPointResult); }
/// <summary> /// <p> /// Query a circular area constructed by a center point and its radius. /// </p> /// <b>Sample usage:</b> /// <pre> /// GeoPoint centerPoint = new GeoPoint(47.5, -122.3); /// QueryRadiusRequest queryRadiusRequest = new QueryRadiusRequest(centerPoint, 100); /// QueryRadiusResult queryRadiusResult = geoIndexManager.queryRadius(queryRadiusRequest); /// for (Map<String, AttributeValue> item : queryRadiusResult.getItem()) { /// System.out.println("item: " + item); /// } /// </pre> /// </summary> /// <param name="queryRadiusRequest">Container for the necessary parameters to execute radius query request.</param> /// <returns>Result of radius query request.</returns> public async Task <QueryRadiusResult> QueryRadiusAsync(QueryRadiusRequest queryRadiusRequest, CancellationToken cancellationToken = default(CancellationToken)) { if (queryRadiusRequest == null) { throw new ArgumentNullException("queryRadiusRequest"); } if (queryRadiusRequest.RadiusInMeter <= 0 || queryRadiusRequest.RadiusInMeter > S2LatLng.EarthRadiusMeters) { throw new ArgumentOutOfRangeException("queryRadiusRequest", "RadiusInMeter needs to be > 0 and <= " + S2LatLng.EarthRadiusMeters); } var latLngRect = S2Util.GetBoundingLatLngRect(queryRadiusRequest); var cellUnion = S2Manager.FindCellIds(latLngRect); var ranges = MergeCells(cellUnion); var result = await DispatchQueries(ranges, queryRadiusRequest, cancellationToken).ConfigureAwait(false); return(new QueryRadiusResult(result)); }
public SubscriptionUpdateRequestBuilder SetLocation(Location location) { _removedProperties.Remove("Location"); _removedProperties.Remove("LocationHash"); _updatedProperties.Add(new UpdatedSubscriberProperty { Name = "Location", Type = typeof(string), Value = $"{location.Latitude},{location.Longitude}" }); _updatedProperties.Add(new UpdatedSubscriberProperty { Name = "LocationHash", Type = typeof(ulong), Value = S2Manager.GenerateGeohash(location.Latitude, location.Longitude) }); return(this); }
private async Task RunGeoQuery(GeoQueryRequest request, GeoQueryResult geoQueryResult, GeohashRange range, CancellationToken cancellationToken) { var queryRequest = request.QueryRequest.CopyQueryRequest(); var hashKey = S2Manager.GenerateHashKey(range.RangeMin, _config.HashKeyLength); var results = await _dynamoDBManager.QueryGeohashAsync(queryRequest, hashKey, range, cancellationToken).ConfigureAwait(false); foreach (var queryResult in results) { cancellationToken.ThrowIfCancellationRequested(); // This is a concurrent collection geoQueryResult.QueryResults.Add(queryResult); var filteredQueryResult = Filter(queryResult.Items, request); // this is a concurrent collection foreach (var r in filteredQueryResult) { geoQueryResult.Items.Add(r); } } }
public async Task <IEnumerable <int> > GetAsync(double magnitude, double latitude, double longitude, int searchRadius) { var result = new List <int>(); var searchRectangle = S2Manager.GetBoundingLatLngRect(latitude, longitude, searchRadius); Dictionary <string, Condition> conditions = new Dictionary <string, Condition> { { "Magnitude", new Condition { ComparisonOperator = ComparisonOperator.LE, AttributeValueList = new List <AttributeValue> { new AttributeValue { N = magnitude.ToString() } } } } }; Dictionary <string, AttributeValue> lastEvaluatedKey = null; do { ScanRequest request = new ScanRequest { TableName = _tableName, ScanFilter = conditions }; if (lastEvaluatedKey != null && lastEvaluatedKey.ContainsKey("chatid")) { request.ExclusiveStartKey["chatid"] = lastEvaluatedKey["chatid"]; } ScanResponse scanResponse = await _amazonDynamoDB.ScanAsync(request); foreach (var item in scanResponse.Items) { if (item.ContainsKey("chatid") && int.TryParse(item["chatid"].S, out int chatId)) { if (item.ContainsKey("LocationHash")) { if (ulong.TryParse(item["LocationHash"].N, out ulong locationHash) && searchRectangle.Intersects(new S2Cell(new S2CellId(locationHash)))) { result.Add(chatId); } } else { result.Add(chatId); } } } lastEvaluatedKey = scanResponse.LastEvaluatedKey; } while (lastEvaluatedKey != null && lastEvaluatedKey.Count > 0); return(result); }