Skip to content

Commit

Permalink
refactor: update to aws-sdk v3
Browse files Browse the repository at this point in the history
  • Loading branch information
renet committed Oct 3, 2021
1 parent d493570 commit 6b06897
Show file tree
Hide file tree
Showing 7 changed files with 303 additions and 203 deletions.
195 changes: 115 additions & 80 deletions example/index.js
Original file line number Diff line number Diff line change
@@ -1,100 +1,135 @@
const ddbGeo = require('dynamodb-geo');
const AWS = require('aws-sdk');
const uuid = require('uuid');
const {
GeoDataManager,
GeoDataManagerConfiguration,
GeoTableUtil,
} = require("dynamodb-geo-v3");
const {
DynamoDB,
DynamoDBClient,
Endpoint,
waitUntilTableExists,
} = require("@aws-sdk/client-dynamodb");
const uuid = require("uuid");

// Set up AWS
AWS.config.update({
// Use a local DB for the example.
const ddb = new DynamoDB({
credentials: {
accessKeyId: YOUR_AWS_KEY_ID,
secretAccessKey: YOUR_AWS_SECRET_ACCESS_KEY,
region: YOUR_AWS_REGION
},
endpoint: new Endpoint("http://localhost:8000"),
region: YOUR_AWS_REGION,
});
const ddbClient = new DynamoDBClient({
credentials: {
accessKeyId: YOUR_AWS_KEY_ID,
secretAccessKey: YOUR_AWS_SECRET_ACCESS_KEY,
},
endpoint: new Endpoint("http://localhost:8000"),
region: YOUR_AWS_REGION,
});

// Use a local DB for the example.
const ddb = new AWS.DynamoDB({ endpoint: new AWS.Endpoint('http://localhost:8000') });

// Configuration for a new instance of a GeoDataManager. Each GeoDataManager instance represents a table
const config = new ddbGeo.GeoDataManagerConfiguration(ddb, 'capitals');
const config = new GeoDataManagerConfiguration(ddb, "capitals");

// Instantiate the table manager
const capitalsManager = new ddbGeo.GeoDataManager(config);
const capitalsManager = new GeoDataManager(config);

// Use GeoTableUtil to help construct a CreateTableInput.
const createTableInput = ddbGeo.GeoTableUtil.getCreateTableRequest(config);
const createTableInput = GeoTableUtil.getCreateTableRequest(config);

// Tweak the schema as desired
createTableInput.ProvisionedThroughput.ReadCapacityUnits = 2;

console.log('Creating table with schema:');
console.log("Creating table with schema:");
console.dir(createTableInput, { depth: null });

// Create the table
ddb.createTable(createTableInput).promise()
// Wait for it to become ready
.then(function () { return ddb.waitFor('tableExists', { TableName: config.tableName }).promise() })
// Load sample data in batches
.then(function () {
console.log('Loading sample data from capitals.json');
const data = require('./capitals.json');
const putPointInputs = data.map(function (capital) {
return {
RangeKeyValue: { S: uuid.v4() }, // Use this to ensure uniqueness of the hash/range pairs.
GeoPoint: {
latitude: capital.latitude,
longitude: capital.longitude
},
PutItemInput: {
Item: {
country: { S: capital.country },
capital: { S: capital.capital }
}
}
}
});

const BATCH_SIZE = 25;
const WAIT_BETWEEN_BATCHES_MS = 1000;
var currentBatch = 1;
ddb
.createTable(createTableInput)
// Wait for it to become ready
.then(function () {
return waitUntilTableExists(
{ client: ddbClient, maxWaitTime: 30000 },
{ TableName: config.tableName }
);
})
// Load sample data in batches
.then(function () {
console.log("Loading sample data from capitals.json");
const data = require("./capitals.json");
const putPointInputs = data.map(function (capital) {
return {
RangeKeyValue: { S: uuid.v4() }, // Use this to ensure uniqueness of the hash/range pairs.
GeoPoint: {
latitude: capital.latitude,
longitude: capital.longitude,
},
PutItemInput: {
Item: {
country: { S: capital.country },
capital: { S: capital.capital },
},
},
};
});

function resumeWriting() {
if (putPointInputs.length === 0) {
return Promise.resolve();
}
const thisBatch = [];
for (var i = 0, itemToAdd = null; i < BATCH_SIZE && (itemToAdd = putPointInputs.shift()); i++) {
thisBatch.push(itemToAdd);
}
console.log('Writing batch ' + (currentBatch++) + '/' + Math.ceil(data.length / BATCH_SIZE));
return capitalsManager.batchWritePoints(thisBatch).promise()
.then(function () {
return new Promise(function (resolve) {
setInterval(resolve,WAIT_BETWEEN_BATCHES_MS);
});
})
.then(function () {
return resumeWriting()
});
}
const BATCH_SIZE = 25;
const WAIT_BETWEEN_BATCHES_MS = 1000;
var currentBatch = 1;

return resumeWriting().catch(function (error) {
console.warn(error);
});
})
// Perform a radius query
.then(function () {
console.log('Querying by radius, looking 100km from Cambridge, UK.');
return capitalsManager.queryRadius({
RadiusInMeter: 100000,
CenterPoint: {
latitude: 52.225730,
longitude: 0.149593
}
function resumeWriting() {
if (putPointInputs.length === 0) {
return Promise.resolve();
}
const thisBatch = [];
for (
var i = 0, itemToAdd = null;
i < BATCH_SIZE && (itemToAdd = putPointInputs.shift());
i++
) {
thisBatch.push(itemToAdd);
}
console.log(
"Writing batch " +
currentBatch++ +
"/" +
Math.ceil(data.length / BATCH_SIZE)
);
return capitalsManager
.batchWritePoints(thisBatch)
.then(function () {
return new Promise(function (resolve) {
setInterval(resolve, WAIT_BETWEEN_BATCHES_MS);
});
})
})
// Print the results, an array of DynamoDB.AttributeMaps
.then(console.log)
// Clean up
.then(function() { return ddb.deleteTable({ TableName: config.tableName }).promise() })
.catch(console.warn)
.then(function () {
process.exit(0);
});
.then(function () {
return resumeWriting();
});
}

return resumeWriting().catch(function (error) {
console.warn(error);
});
})
// Perform a radius query
.then(function () {
console.log("Querying by radius, looking 100km from Cambridge, UK.");
return capitalsManager.queryRadius({
RadiusInMeter: 100000,
CenterPoint: {
latitude: 52.22573,
longitude: 0.149593,
},
});
})
// Print the results, an array of DynamoDB.AttributeMaps
.then(console.log)
// Clean up
.then(function () {
return ddb.deleteTable({ TableName: config.tableName });
})
.catch(console.warn)
.then(function () {
process.exit(0);
});
2 changes: 1 addition & 1 deletion example/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"dependencies": {
"aws-sdk": "^2.48.0",
"@aws-sdk/client-dynamodb": "^3.34.0",
"dynamodb-geo": "*",
"uuid": "^3.0.1"
}
Expand Down
8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "dynamodb-geo",
"version": "0.4.0",
"name": "dynamodb-geo-v3",
"version": "1.0.0",
"description": "A javascript port of awslabs/dynamodb-geo, for dynamodb geospatial querying",
"scripts": {
"prepublish": "tsc -d",
Expand All @@ -10,8 +10,8 @@
},
"main": "dist/index.js",
"types": "dist/index.d.ts",
"repository": "rh389/dynamodb-geo.js",
"author": "Rob Hogan <[email protected]>",
"repository": "renet/dynamodb-geo-v3",
"author": "René Schubert <[email protected]>",
"license": "Apache-2.0",
"dependencies": {
"@types/long": ">=3",
Expand Down
4 changes: 2 additions & 2 deletions src/dynamodb/DynamoDBManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
* permissions and limitations under the License.
*/

import { GeoDataManagerConfiguration } from "../GeoDataManagerConfiguration";
import {
AttributeValue,
Condition,
Expand All @@ -23,6 +22,8 @@ import {
QueryOutput,
WriteRequest,
} from "@aws-sdk/client-dynamodb";
import * as Long from "long";
import { GeoDataManagerConfiguration } from "../GeoDataManagerConfiguration";
import {
DeletePointInput,
GetPointInput,
Expand All @@ -32,7 +33,6 @@ import {
} from "../types";
import { S2Manager } from "../s2/S2Manager";
import { GeohashRange } from "../model/GeohashRange";
import * as Long from "long";

export class DynamoDBManager {
private config: GeoDataManagerConfiguration;
Expand Down
83 changes: 53 additions & 30 deletions src/s2/S2Util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,45 +2,68 @@ import { QueryRadiusInput, QueryRectangleInput } from "../types";
import { S2LatLng, S2LatLngRect } from "nodes2ts";

export class S2Util {
public static latLngRectFromQueryRectangleInput(geoQueryRequest: QueryRectangleInput): S2LatLngRect {
const queryRectangleRequest = geoQueryRequest as QueryRectangleInput;
public static latLngRectFromQueryRectangleInput(
geoQueryRequest: QueryRectangleInput
): S2LatLngRect {
const queryRectangleRequest = geoQueryRequest as QueryRectangleInput;

const minPoint = queryRectangleRequest.MinPoint;
const maxPoint = queryRectangleRequest.MaxPoint;
const minPoint = queryRectangleRequest.MinPoint;
const maxPoint = queryRectangleRequest.MaxPoint;

let latLngRect: S2LatLngRect = null;
let latLngRect: S2LatLngRect = null;

if (minPoint != null && maxPoint != null) {
const minLatLng = S2LatLng.fromDegrees(minPoint.latitude, minPoint.longitude);
const maxLatLng = S2LatLng.fromDegrees(maxPoint.latitude, maxPoint.longitude);
if (minPoint != null && maxPoint != null) {
const minLatLng = S2LatLng.fromDegrees(
minPoint.latitude,
minPoint.longitude
);
const maxLatLng = S2LatLng.fromDegrees(
maxPoint.latitude,
maxPoint.longitude
);

latLngRect = S2LatLngRect.fromLatLng(minLatLng, maxLatLng);
}
latLngRect = S2LatLngRect.fromLatLng(minLatLng, maxLatLng);
}

return latLngRect;
}
return latLngRect;
}

public static getBoundingLatLngRectFromQueryRadiusInput(geoQueryRequest: QueryRadiusInput): S2LatLngRect {
const centerPoint = geoQueryRequest.CenterPoint;
const radiusInMeter = geoQueryRequest.RadiusInMeter;
public static getBoundingLatLngRectFromQueryRadiusInput(
geoQueryRequest: QueryRadiusInput
): S2LatLngRect {
const centerPoint = geoQueryRequest.CenterPoint;
const radiusInMeter = geoQueryRequest.RadiusInMeter;

const centerLatLng = S2LatLng.fromDegrees(centerPoint.latitude, centerPoint.longitude);
const centerLatLng = S2LatLng.fromDegrees(
centerPoint.latitude,
centerPoint.longitude
);

const latReferenceUnit = centerPoint.latitude > 0.0 ? -1.0 : 1.0;
const latReferenceLatLng = S2LatLng.fromDegrees(centerPoint.latitude + latReferenceUnit,
centerPoint.longitude);
const lngReferenceUnit = centerPoint.longitude > 0.0 ? -1.0 : 1.0;
const lngReferenceLatLng = S2LatLng.fromDegrees(centerPoint.latitude, centerPoint.longitude
+ lngReferenceUnit);
const latReferenceUnit = centerPoint.latitude > 0.0 ? -1.0 : 1.0;
const latReferenceLatLng = S2LatLng.fromDegrees(
centerPoint.latitude + latReferenceUnit,
centerPoint.longitude
);
const lngReferenceUnit = centerPoint.longitude > 0.0 ? -1.0 : 1.0;
const lngReferenceLatLng = S2LatLng.fromDegrees(
centerPoint.latitude,
centerPoint.longitude + lngReferenceUnit
);

const latForRadius = radiusInMeter / (centerLatLng.getEarthDistance(latReferenceLatLng) as any).toNumber();
const lngForRadius = radiusInMeter / (centerLatLng.getEarthDistance(lngReferenceLatLng) as any).toNumber();
const latForRadius =
radiusInMeter / centerLatLng.getEarthDistance(latReferenceLatLng);
const lngForRadius =
radiusInMeter / centerLatLng.getEarthDistance(lngReferenceLatLng);

const minLatLng = S2LatLng.fromDegrees(centerPoint.latitude - latForRadius,
centerPoint.longitude - lngForRadius);
const maxLatLng = S2LatLng.fromDegrees(centerPoint.latitude + latForRadius,
centerPoint.longitude + lngForRadius);
const minLatLng = S2LatLng.fromDegrees(
centerPoint.latitude - latForRadius,
centerPoint.longitude - lngForRadius
);
const maxLatLng = S2LatLng.fromDegrees(
centerPoint.latitude + latForRadius,
centerPoint.longitude + lngForRadius
);

return S2LatLngRect.fromLatLng(minLatLng, maxLatLng);
}
return S2LatLngRect.fromLatLng(minLatLng, maxLatLng);
}
}
Loading

0 comments on commit 6b06897

Please sign in to comment.