Esempio n. 1
0
        /*
         * 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);
        }
Esempio n. 2
0
        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);
        }
Esempio n. 3
0
        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);
        }
Esempio n. 4
0
        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));
        }
Esempio n. 5
0
        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);
        }
Esempio n. 6
0
        /// <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&lt;String, AttributeValue&gt; item : queryRadiusResult.getItem()) {
        ///         System.out.println(&quot;item: &quot; + 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);
        }
Esempio n. 8
0
        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);
                }
            }
        }
Esempio n. 9
0
        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);
        }