{"_id":"@ai-t/dynamodb-geo","_rev":"3-46bdd1c34019296f5ea1cbedc92f40f1","time":{"created":"2023-05-17T09:56:09.092Z","1.0.0":"2023-05-12T04:12:56.647Z","modified":"2023-05-18T03:35:20.366Z","1.0.1":"2023-05-17T09:56:09.348Z","1.0.2":"2023-05-18T03:35:20.222Z"},"name":"@ai-t/dynamodb-geo","dist-tags":{"latest":"1.0.2"},"versions":{"1.0.1":{"name":"@ai-t/dynamodb-geo","version":"1.0.1","description":"A javascript port of awslabs/dynamodb-geo, for dynamodb geospatial querying","scripts":{"prepublish":"tsc -d","clean":"rm -rf dist","build":"tsc -d","test":"mocha --require ts-node/register test/**/*.ts"},"main":"dist/index.js","types":"dist/index.d.ts","repository":{"type":"git","url":"git+https://github.com/banv/dynamodb-geo-v3.git"},"author":{"name":"AI&T"},"license":"Apache-2.0","dependencies":{"@types/long":">=3","nodes2ts":"^2.0.0"},"devDependencies":{"@types/chai":"^4.0.0","@types/mocha":"^2.2.41","chai":"^4.0.1","mocha":"^3.3.0","ts-node":"^10.2.1","typescript":"^4.4.3"},"peerDependencies":{"@aws-sdk/client-dynamodb":"^3.34.0"},"bugs":{"url":"https://github.com/banv/dynamodb-geo-v3/issues"},"homepage":"https://github.com/banv/dynamodb-geo-v3#readme","directories":{"example":"example","test":"test"},"gitHead":"5d2da1dcd16bc27f7729a10ee33770edda82ad57","_id":"@ai-t/dynamodb-geo@1.0.1","_nodeVersion":"18.12.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-JaXh50+VqASCgO4e7myrMo5KqWr3ZpKCvyh0suPTwtewUHLHzIjO/aICy/1t9oLBfHYjhaxBp3q1/J1p311tJA==","shasum":"d44c421977b441aa0b44481442af3412cca02c73","tarball":"https://registry.npmjs.org/@ai-t/dynamodb-geo/-/dynamodb-geo-1.0.1.tgz","fileCount":29,"unpackedSize":92924,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIG89RBKSt4hRJ+daeGkpa7suqmEsPbQVMmQz7rT09Cp8AiAYJ1v3tHqcDDXWpNj6Kx6v4jptE43LDqS4bW/nM5l6hA=="}]},"_npmUser":{"name":"ai-t","email":"banv+1@ai-t.vn"},"maintainers":[{"name":"ai-t","email":"banv+1@ai-t.vn"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/dynamodb-geo_1.0.1_1684317369170_0.5005788824663424"},"_hasShrinkwrap":false},"1.0.2":{"name":"@ai-t/dynamodb-geo","version":"1.0.2","description":"A javascript port of awslabs/dynamodb-geo, for dynamodb geospatial querying","scripts":{"prepublish":"tsc -d","clean":"rm -rf dist","build":"tsc -d","test":"mocha --require ts-node/register test/**/*.ts"},"main":"dist/index.js","types":"dist/index.d.ts","repository":{"type":"git","url":"git+https://github.com/banv/dynamodb-geo-v3.git"},"author":{"name":"AI&T"},"license":"Apache-2.0","dependencies":{"@types/long":">=3","nodes2ts":"^2.0.0"},"devDependencies":{"@types/chai":"^4.0.0","@types/mocha":"^2.2.41","chai":"^4.0.1","mocha":"^3.3.0","ts-node":"^10.2.1","typescript":"^4.4.3"},"peerDependencies":{"@aws-sdk/client-dynamodb":"^3.34.0"},"bugs":{"url":"https://github.com/banv/dynamodb-geo-v3/issues"},"homepage":"https://github.com/banv/dynamodb-geo-v3#readme","directories":{"example":"example","test":"test"},"gitHead":"ee286c2d2ef190aef5d49cff8ca5f616f090e40d","_id":"@ai-t/dynamodb-geo@1.0.2","_nodeVersion":"18.12.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-nCj2VPG8no+6ngdHlH1WAqgeZnxX475i4sMQOzGJ9AxXW7wYW3AjfHusp9LAAU3AHHhkv2AI2dzuZBd7ySdqhg==","shasum":"607de3e79f0f98758b1072052c27109fe0033f09","tarball":"https://registry.npmjs.org/@ai-t/dynamodb-geo/-/dynamodb-geo-1.0.2.tgz","fileCount":30,"unpackedSize":102491,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD19ELLSZhWZ8l/NMBQmrJCh8rvZxqrxgLPfHp1+1YjbAIgHGDBtblCtoaoJ2XgXwtsNUO9OJlvqB3dmoLPpqWHVY8="}]},"_npmUser":{"name":"ai-t","email":"banv+1@ai-t.vn"},"maintainers":[{"name":"ai-t","email":"banv+1@ai-t.vn"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/dynamodb-geo_1.0.2_1684380919997_0.48742103997217234"},"_hasShrinkwrap":false}},"maintainers":[{"name":"ai-t","email":"banv+1@ai-t.vn"}],"description":"A javascript port of awslabs/dynamodb-geo, for dynamodb geospatial querying","homepage":"https://github.com/banv/dynamodb-geo-v3#readme","repository":{"type":"git","url":"git+https://github.com/banv/dynamodb-geo-v3.git"},"author":{"name":"AI&T"},"bugs":{"url":"https://github.com/banv/dynamodb-geo-v3/issues"},"license":"Apache-2.0","readme":"[![npm version](https://badge.fury.io/js/dynamodb-geo-v3.svg)](https://badge.fury.io/js/dynamodb-geo-v3)\n\n# Geo Library for Amazon DynamoDB\n\nThis project is an unofficial port of [awslabs/dynamodb-geo][dynamodb-geo], bringing creation and querying of geospatial data to Node JS developers using [Amazon DynamoDB][dynamodb].\n\n## Features\n\n- **Box Queries:** Return all of the items that fall within a pair of geo points that define a rectangle as projected onto a sphere.\n- **Radius Queries:** Return all of the items that are within a given radius of a geo point.\n- **Basic CRUD Operations:** Create, retrieve, update, and delete geospatial data items.\n- **Customizable:** Access to raw request and result objects from the AWS SDK for javascript.\n- **Fully Typed:** This port is written in typescript and declaration files are bundled into releases.\n\n## Installation\n\nUsing [npm] or [yarn]:\n\n```sh\nnpm install --save dynamodb-geo-v3\n\n# or\n\nyarn add dynamodb-geo-v3\n```\n\n## Getting started\n\nFirst you'll need to import the DynamoDB Client of the AWS SDK and set up your DynamoDB connection:\n\n```js\nconst { DynamoDB, Endpoint } = require(\"@aws-sdk/client-dynamodb\");\nconst ddb = new DynamoDB({ endpoint: new Endpoint(\"http://localhost:8000\") }); // Local development\n```\n\nNext you must create an instance of `GeoDataManagerConfiguration` for each geospatial table you wish to interact with. This is a container for various options (see API below), but you must always provide a `DynamoDB` instance and a table name.\n\n```js\nconst { GeoDataManagerConfiguration } = require(\"dynamodb-geo-v3\");\nconst config = new GeoDataManagerConfiguration(ddb, \"MyGeoTable\");\n```\n\nYou may modify the config to change defaults.\n\n```js\nconfig.longitudeFirst = true; // Use spec-compliant GeoJSON, incompatible with awslabs/dynamodb-geo\n```\n\nFinally, you should instantiate a manager to query and write to the table using this config object.\n\n```js\nconst { GeoDataManager } = require(\"dynamodb-geo-v3\");\nconst myGeoTableManager = new GeoDataManager(config);\n```\n\n## Choosing a `hashKeyLength` (optimising for performance and cost)\n\nThe `hashKeyLength` is the number of most significant digits (in base 10) of the 64-bit geo hash to use as the hash key. Larger numbers will allow small geographical areas to be spread across DynamoDB partitions, but at the cost of performance as more [queries][dynamodb-query] need to be executed for box/radius searches that span hash keys. See [these tests][hashkeylength-tests] for an idea of how query performance scales with `hashKeyLength` for different search radii.\n\nIf your data is sparse, a large number will mean more RCUs since more empty queries will be executed and each has a minimum cost. However if your data is dense and `hashKeyLength` too short, more RCUs will be needed to read a hash key and a higher proportion will be discarded by server-side filtering.\n\nFrom the [AWS `Query` documentation][dynamodb-query]\n\n> DynamoDB calculates the number of read capacity units consumed based on item size, not on the amount of data that is returned to an application. ... **The number will also be the same whether or not you use a `FilterExpression`**\n\nOptimally, you should pick the largest `hashKeyLength` your usage scenario allows. The wider your typical radius/box queries, the smaller it will need to be.\n\nNote that the [Java version][dynamodb-geo-v3] uses a `hashKeyLength` of `6` by default. The same value will need to be used if you access the same data with both clients.\n\nThis is an important early choice, since changing your `hashKeyLength` will mean recreating your data.\n\n## Creating a table\n\n`GeoTableUtil` has a static method `getCreateTableRequest` for helping you prepare a [DynamoDB CreateTable request][createtable] request, given a `GeoDataManagerConfiguration`.\n\nYou can modify this request as desired before executing it using AWS's DynamoDB SDK.\n\nExample:\n\n```js\n// Pick a hashKeyLength appropriate to your usage\nconfig.hashKeyLength = 3;\n\n// Use GeoTableUtil to help construct a CreateTableInput.\nconst { GeoTableUtil } = require(\"dynamodb-geo-v3\");\nconst createTableInput = GeoTableUtil.getCreateTableRequest(config);\n\n// Tweak the schema as desired\ncreateTableInput.ProvisionedThroughput.ReadCapacityUnits = 2;\n\nconsole.log(\"Creating table with schema:\");\nconsole.dir(createTableInput, { depth: null });\n\n// Create the table\nddb\n  .createTable(createTableInput)\n  // Wait for it to become ready\n  .then(() => {\n    return ddb.waitFor(\"tableExists\", { TableName: config.tableName });\n  })\n  .then(() => {\n    console.log(\"Table created and ready!\");\n  });\n```\n\n## Adding data\n\n```js\nmyGeoTableManager\n  .putPoint({\n    RangeKeyValue: { S: \"1234\" }, // Use this to ensure uniqueness of the hash/range pairs.\n    GeoPoint: {\n      // An object specifying latitutde and longitude as plain numbers. Used to build the geohash, the hashkey and geojson data\n      latitude: 51.51,\n      longitude: -0.13,\n    },\n    PutItemInput: {\n      // Passed through to the underlying DynamoDB.putItem request. TableName is filled in for you.\n      Item: {\n        // The primary key, geohash and geojson data is filled in for you\n        country: { S: \"UK\" }, // Specify attribute values using { type: value } objects, like the DynamoDB API.\n        capital: { S: \"London\" },\n      },\n      // ... Anything else to pass through to `putItem`, eg ConditionExpression\n    },\n  })\n  .then(() => {\n    console.log(\"Done!\");\n  });\n```\n\nSee also [DynamoDB PutItem request][putitem]\n\n## Updating a specific point\n\nNote that you cannot update the hash key, range key, geohash or geoJson. If you want to change these, you'll need to recreate the record.\n\nYou must specify a `RangeKeyValue`, a `GeoPoint`, and an `UpdateItemInput` matching the [DynamoDB UpdateItem][updateitem] request (`TableName` and `Key` are filled in for you).\n\n```js\nmyGeoTableManager\n  .updatePoint({\n    RangeKeyValue: { S: \"1234\" },\n    GeoPoint: {\n      // An object specifying latitutde and longitude as plain numbers.\n      latitude: 51.51,\n      longitude: -0.13,\n    },\n    UpdateItemInput: {\n      // TableName and Key are filled in for you\n      UpdateExpression: \"SET country = :newName\",\n      ExpressionAttributeValues: {\n        \":newName\": { S: \"United Kingdom\" },\n      },\n    },\n  })\n  .then(() => {\n    console.log(\"Done!\");\n  });\n```\n\n## Deleting a specific point\n\nYou must specify a `RangeKeyValue` and a `GeoPoint`. Optionally, you can pass `DeleteItemInput` matching [DynamoDB DeleteItem][deleteitem] request (`TableName` and `Key` are filled in for you).\n\n```js\nmyGeoTableManager\n  .deletePoint({\n    RangeKeyValue: { S: \"1234\" },\n    GeoPoint: {\n      // An object specifying latitutde and longitude as plain numbers.\n      latitude: 51.51,\n      longitude: -0.13,\n    },\n    DeleteItemInput: {\n      // Optional, any additional parameters to pass through.\n      // TableName and Key are filled in for you\n      // Example: Only delete if the point does not have a country name set\n      ConditionExpression: \"attribute_not_exists(country)\",\n    },\n  })\n  .then(() => {\n    console.log(\"Done!\");\n  });\n```\n\n## Rectangular queries\n\nQuery by rectangle by specifying a `MinPoint` and `MaxPoint`.\n\n```js\n// Querying a rectangle\nmyGeoTableManager\n  .queryRectangle({\n    MinPoint: {\n      latitude: 52.22573,\n      longitude: 0.149593,\n    },\n    MaxPoint: {\n      latitude: 52.889499,\n      longitude: 0.848383,\n    },\n  })\n  // Print the results, an array of DynamoDB.AttributeMaps\n  .then(console.log);\n```\n\n## Radius queries\n\nQuery by radius by specifying a `CenterPoint` and `RadiusInMeter`.\n\n```js\n// Querying 100km from Cambridge, UK\nmyGeoTableManager\n  .queryRadius({\n    RadiusInMeter: 100000,\n    CenterPoint: {\n      latitude: 52.22573,\n      longitude: 0.149593,\n    },\n  })\n  // Print the results, an array of DynamoDB.AttributeMaps\n  .then(console.log);\n```\n\n## Batch operations\n\nTODO: Docs (see [the example][example] for an example of a batch write)\n\n## Configuration reference\n\nThese are public properties of a `GeoDataManagerConfiguration` instance. After creating the config object you may modify these properties.\n\n#### consistentRead: boolean = false\n\nWhether queries use the [`ConsistentRead`][readconsistency] option (for strongly consistent reads) or not (for eventually consistent reads, at half the cost).\n\nThis can also be overridden for individual queries as a query config option.\n\n#### longitudeFirst: boolean = true\n\nThis library will automatically add GeoJSON-style position data to your stored items. The [GeoJSON standard][geojson] uses `[lon,lat]` ordering, but [awslabs/dynamodb-geo][dynamodb-geo] uses `[lat,lng]`.\n\nThis fork allows you to choose between [awslabs/dynamodb-geo][dynamodb-geo] compatibility and GeoJSON standard compliance.\n\n- Use `false` (`[lat, lon]`) for compatibility with [awslabs/dynamodb-geo][dynamodb-geo]\n- Use `true` (`[lon, lat]`) for GeoJSON standard compliance. (default)\n\nNote that this value should match the state of your existing data - if you change it you must update your database manually, or you'll end up with ambiguously mixed data.\n\n#### geoJsonPointType: \"Point\" | \"POINT\" = \"Point\"\n\nThe value of the `type` attribute in recorded GeoJSON points. Should normally be `\"Point\"`, which is standards compliant.\n\nUse `\"POINT\"` for compatibility with [awslabs/dynamodb-geo][dynamodb-geo].\n\nThis setting is only relevant for writes. This library doesn't inspect or set this value when reading/querying.\n\n#### geohashAttributeName: string = \"geohash\"\n\nThe name of the attribute storing the full 64-bit geohash. Its value is auto-generated based on item coordinates.\n\n#### hashKeyAttributeName: string = \"hashKey\"\n\nThe name of the attribute storing the first `hashKeyLength` digits (default 2) of the geo hash, used as the hash (aka partition) part of a [hash/range primary key pair][hashrange]. Its value is auto-generated based on item coordinates.\n\n#### hashKeyLength: number = 2\n\nSee [above][choosing-hashkeylength].\n\n#### rangeKeyAttributeName: string = \"rangeKey\"\n\nThe name of the attribute storing the range key, used as the range (aka sort) part of a [hash/range key primary key pair][hashrange]. Its value must be specified by you (hash-range pairs must be unique).\n\n#### geoJsonAttributeName: string = \"geoJson\"\n\nThe name of the attribute which will contain the longitude/latitude pair in a GeoJSON-style point (see also `longitudeFirst`).\n\n#### geohashIndexName: string = \"geohash-index\"\n\nThe name of the index to be created against the geohash. Only used for creating new tables.\n\n## Example\n\nSee the [example on Github][example]\n\n## Limitations\n\n### No composite key support\n\nCurrently, the library does not support composite keys. You may want to add tags such as restaurant, bar, and coffee shop, and search locations of a specific category; however, it is currently not possible. You need to create a table for each tag and store the items separately.\n\n### Queries retrieve all paginated data\n\nAlthough low level [DynamoDB Query][dynamodb-query] requests return paginated results, this library automatically pages through the entire result set. When querying a large area with many points, a lot of Read Capacity Units may be consumed.\n\n### More Read Capacity Units\n\nThe library retrieves candidate Geo points from the cells that intersect the requested bounds. The library then post-processes the candidate data, filtering out the specific points that are outside the requested bounds. Therefore, the consumed Read Capacity Units will be higher than the final results dataset. Typically 8 queries are exectued per radius or box search.\n\n### High memory consumption\n\nBecause all paginated `Query` results are loaded into memory and processed, it may consume substantial amounts of memory for large datasets.\n\n### Dataset density limitation\n\nThe Geohash used in this library is roughly centimeter precision. Therefore, the library is not suitable if your dataset has much higher density.\n\n[npm]: https://www.npmjs.com\n[yarn]: https://yarnpkg.com\n[updateitem]: http://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_UpdateItem.html\n[deleteitem]: http://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_DeleteItem.html\n[putitem]: http://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_PutItem.html\n[createtable]: http://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_CreateTable.html\n[hashrange]: http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.CoreComponents.html#HowItWorks.CoreComponents.PrimaryKey\n[readconsistency]: http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.ReadConsistency.html\n[geojson]: https://geojson.org/geojson-spec.html\n[example]: https://github.com/rh389/dynamodb-geo-v3.js/tree/master/example\n[dynamodb-geo-v3]: https://github.com/awslabs/dynamodb-geo\n[dynamodb]: http://aws.amazon.com/dynamodb\n[dynamodb-query]: http://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Query.html\n[hashkeylength-tests]: https://github.com/rh389/dynamodb-geo-v3.js/blob/master/test/integration/hashKeyLength.ts\n[choosing-hashkeylength]: #choosing-a-hashkeylength-optimising-for-performance-and-cost\n\n## Credit\n\nCredit to the original implementation goes to [Rob Hogan](https://github.com/rh389), as this repository was forked from his [original repository](https://github.com/rh389/dynamodb-geo.js), just to refactor it to use the [DynamoDB Client - AWS SDK for JavaScript v3](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/clients/client-dynamodb/).\n","readmeFilename":"README.md"}