/// <summary> /// Merge continuous cells in cellUnion and return a list of merged GeohashRanges. /// </summary> /// <param name="cellUnion">Container for multiple cells.</param> /// <returns>A list of merged GeohashRanges.</returns> private static List <GeohashRange> MergeCells(S2CellUnion cellUnion) { var ranges = new List <GeohashRange>(); foreach (var c in cellUnion.CellIds) { var range = new GeohashRange(c.RangeMin.Id, c.RangeMax.Id); var wasMerged = false; foreach (var r in ranges) { if (r.TryMerge(range)) { wasMerged = true; break; } } if (!wasMerged) { ranges.Add(range); } } return(ranges); }
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); } } }
/// <summary> /// Query Amazon DynamoDB /// </summary> /// <param name="queryRequest"></param> /// <param name="hashKey">Hash key for the query request.</param> /// <param name="range">The range of geohashs to query.</param> /// <returns>The query result.</returns> public async Task <IReadOnlyList <QueryResponse> > QueryGeohashAsync(QueryRequest queryRequest, ulong hashKey, GeohashRange range, CancellationToken cancellationToken = default(CancellationToken)) { if (queryRequest == null) { throw new ArgumentNullException("queryRequest"); } if (range == null) { throw new ArgumentNullException("range"); } var queryResults = new List <QueryResponse>(); IDictionary <String, AttributeValue> lastEvaluatedKey = null; do { var keyConditions = new Dictionary <String, Condition>(); var hashKeyCondition = new Condition { ComparisonOperator = ComparisonOperator.EQ, AttributeValueList = new List <AttributeValue> { new AttributeValue { N = hashKey.ToString(CultureInfo.InvariantCulture) } } }; keyConditions.Add(_config.HashKeyAttributeName, hashKeyCondition); var minRange = new AttributeValue { N = range.RangeMin.ToString(CultureInfo.InvariantCulture) }; var maxRange = new AttributeValue { N = range.RangeMax.ToString(CultureInfo.InvariantCulture) }; var geohashCondition = new Condition { ComparisonOperator = ComparisonOperator.BETWEEN, AttributeValueList = new List <AttributeValue> { minRange, maxRange } }; keyConditions.Add(_config.GeohashAttributeName, geohashCondition); queryRequest.TableName = _config.TableName; queryRequest.KeyConditions = keyConditions; queryRequest.IndexName = _config.GeohashIndexName; queryRequest.ConsistentRead = true; queryRequest.ReturnConsumedCapacity = ReturnConsumedCapacity.TOTAL; if (lastEvaluatedKey != null && lastEvaluatedKey.Count > 0) { queryRequest.ExclusiveStartKey[_config.HashKeyAttributeName] = lastEvaluatedKey[_config.HashKeyAttributeName]; queryRequest.ExclusiveStartKey[_config.RangeKeyAttributeName] = lastEvaluatedKey[_config.RangeKeyAttributeName]; queryRequest.ExclusiveStartKey[_config.GeohashAttributeName] = lastEvaluatedKey[_config.GeohashAttributeName]; } QueryResponse queryResult = await _config.DynamoDBClient.QueryAsync(queryRequest, cancellationToken).ConfigureAwait(false); queryResults.Add(queryResult); lastEvaluatedKey = queryResult.LastEvaluatedKey; } while (lastEvaluatedKey != null && lastEvaluatedKey.Count > 0); return(queryResults); }