@exabugs/dynamodb-client 1.1.1 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +58 -0
- package/dist/server/handler.cjs +379 -29
- package/dist/server/handler.cjs.map +4 -4
- package/dist/server/query/index.d.ts +1 -0
- package/dist/server/query/index.d.ts.map +1 -1
- package/dist/server/query/index.js +1 -0
- package/dist/server/query/index.js.map +1 -1
- package/dist/server/query/nearSearch.d.ts +50 -0
- package/dist/server/query/nearSearch.d.ts.map +1 -0
- package/dist/server/query/nearSearch.js +100 -0
- package/dist/server/query/nearSearch.js.map +1 -0
- package/dist/server/shadow/generator.d.ts.map +1 -1
- package/dist/server/shadow/generator.js +13 -1
- package/dist/server/shadow/generator.js.map +1 -1
- package/dist/shared/geohash/index.d.ts +6 -0
- package/dist/shared/geohash/index.d.ts.map +1 -0
- package/dist/shared/geohash/index.js +6 -0
- package/dist/shared/geohash/index.js.map +1 -0
- package/dist/shared/geohash/types.d.ts +103 -0
- package/dist/shared/geohash/types.d.ts.map +1 -0
- package/dist/shared/geohash/types.js +25 -0
- package/dist/shared/geohash/types.js.map +1 -0
- package/dist/shared/geohash/utils.d.ts +62 -0
- package/dist/shared/geohash/utils.d.ts.map +1 -0
- package/dist/shared/geohash/utils.js +135 -0
- package/dist/shared/geohash/utils.js.map +1 -0
- package/dist/shared/index.d.ts +1 -0
- package/dist/shared/index.d.ts.map +1 -1
- package/dist/shared/index.js +2 -0
- package/dist/shared/index.js.map +1 -1
- package/package.json +3 -1
- package/terraform/modules/parameter-store/outputs.tf +0 -34
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/server/query/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EACL,qBAAqB,EACrB,KAAK,wBAAwB,EAC7B,KAAK,eAAe,EACpB,KAAK,WAAW,GACjB,MAAM,gBAAgB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/server/query/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EACL,qBAAqB,EACrB,KAAK,wBAAwB,EAC7B,KAAK,eAAe,EACpB,KAAK,WAAW,GACjB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EAAE,iBAAiB,EAAE,KAAK,gBAAgB,EAAE,MAAM,iBAAiB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/server/query/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EACL,qBAAqB,GAItB,MAAM,gBAAgB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/server/query/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EACL,qBAAqB,GAItB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EAAE,iBAAiB,EAAyB,MAAM,iBAAiB,CAAC"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GeoHash近隣検索ロジック
|
|
3
|
+
*
|
|
4
|
+
* Records Lambdaで検証済みの9ブロック検索アルゴリズムを移植
|
|
5
|
+
*/
|
|
6
|
+
import { type DocumentWithDistance, type GeoHashConfig, type NearQuery } from '../../shared/geohash/index.js';
|
|
7
|
+
/**
|
|
8
|
+
* 9ブロック検索の結果
|
|
9
|
+
*/
|
|
10
|
+
export interface NearSearchResult<T> {
|
|
11
|
+
/** 距離付きドキュメント */
|
|
12
|
+
documents: Array<T & DocumentWithDistance>;
|
|
13
|
+
/** 検索メタデータ */
|
|
14
|
+
metadata: {
|
|
15
|
+
/** 検索反復回数 */
|
|
16
|
+
iterations: number;
|
|
17
|
+
/** 候補数 */
|
|
18
|
+
candidatesFound: number;
|
|
19
|
+
/** 要求件数 */
|
|
20
|
+
requestedLimit: number;
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* 9ブロック検索を実行
|
|
25
|
+
*
|
|
26
|
+
* Records Lambdaの`findVenueCandidates`関数のロジックを移植。
|
|
27
|
+
* 段階的に精度を緩和しながら、9ブロック(中心 + 隣接8方向)を検索します。
|
|
28
|
+
*
|
|
29
|
+
* @param nearQuery - $nearクエリ
|
|
30
|
+
* @param fieldName - GeoHashフィールド名
|
|
31
|
+
* @param limit - 取得件数
|
|
32
|
+
* @param searchFunction - 実際の検索を実行する関数
|
|
33
|
+
* @param config - GeoHash設定
|
|
34
|
+
* @returns 距離付きドキュメントと検索メタデータ
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* ```typescript
|
|
38
|
+
* const result = await executeNearSearch(
|
|
39
|
+
* { latitude: 35.6812, longitude: 139.7671, maxDistance: 5000 },
|
|
40
|
+
* 'location',
|
|
41
|
+
* 10,
|
|
42
|
+
* async (geohashPrefix) => {
|
|
43
|
+
* // DynamoDBから検索
|
|
44
|
+
* return await collection.find({ geohash: { $regex: `^${geohashPrefix}` } }).toArray();
|
|
45
|
+
* }
|
|
46
|
+
* );
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
49
|
+
export declare function executeNearSearch<T extends Record<string, unknown>>(nearQuery: NearQuery, fieldName: string, limit: number, searchFunction: (geohashPrefix: string) => Promise<T[]>, config?: GeoHashConfig): Promise<NearSearchResult<T>>;
|
|
50
|
+
//# sourceMappingURL=nearSearch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nearSearch.d.ts","sourceRoot":"","sources":["../../../src/server/query/nearSearch.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAEL,KAAK,oBAAoB,EACzB,KAAK,aAAa,EAClB,KAAK,SAAS,EAOf,MAAM,+BAA+B,CAAC;AAEvC;;GAEG;AACH,MAAM,WAAW,gBAAgB,CAAC,CAAC;IACjC,iBAAiB;IACjB,SAAS,EAAE,KAAK,CAAC,CAAC,GAAG,oBAAoB,CAAC,CAAC;IAC3C,cAAc;IACd,QAAQ,EAAE;QACR,aAAa;QACb,UAAU,EAAE,MAAM,CAAC;QACnB,UAAU;QACV,eAAe,EAAE,MAAM,CAAC;QACxB,WAAW;QACX,cAAc,EAAE,MAAM,CAAC;KACxB,CAAC;CACH;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAsB,iBAAiB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACvE,SAAS,EAAE,SAAS,EACpB,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,EACb,cAAc,EAAE,CAAC,aAAa,EAAE,MAAM,KAAK,OAAO,CAAC,CAAC,EAAE,CAAC,EACvD,MAAM,GAAE,aAAsC,GAC7C,OAAO,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAwF9B"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GeoHash近隣検索ロジック
|
|
3
|
+
*
|
|
4
|
+
* Records Lambdaで検証済みの9ブロック検索アルゴリズムを移植
|
|
5
|
+
*/
|
|
6
|
+
import { DEFAULT_GEOHASH_CONFIG, calculateDistance, encodeGeoHash, extractCoordinatesFromNearQuery, extractMaxDistanceFromNearQuery, extractMinDistanceFromNearQuery, getNeighborGeoHashes, } from '../../shared/geohash/index.js';
|
|
7
|
+
/**
|
|
8
|
+
* 9ブロック検索を実行
|
|
9
|
+
*
|
|
10
|
+
* Records Lambdaの`findVenueCandidates`関数のロジックを移植。
|
|
11
|
+
* 段階的に精度を緩和しながら、9ブロック(中心 + 隣接8方向)を検索します。
|
|
12
|
+
*
|
|
13
|
+
* @param nearQuery - $nearクエリ
|
|
14
|
+
* @param fieldName - GeoHashフィールド名
|
|
15
|
+
* @param limit - 取得件数
|
|
16
|
+
* @param searchFunction - 実際の検索を実行する関数
|
|
17
|
+
* @param config - GeoHash設定
|
|
18
|
+
* @returns 距離付きドキュメントと検索メタデータ
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```typescript
|
|
22
|
+
* const result = await executeNearSearch(
|
|
23
|
+
* { latitude: 35.6812, longitude: 139.7671, maxDistance: 5000 },
|
|
24
|
+
* 'location',
|
|
25
|
+
* 10,
|
|
26
|
+
* async (geohashPrefix) => {
|
|
27
|
+
* // DynamoDBから検索
|
|
28
|
+
* return await collection.find({ geohash: { $regex: `^${geohashPrefix}` } }).toArray();
|
|
29
|
+
* }
|
|
30
|
+
* );
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
export async function executeNearSearch(nearQuery, fieldName, limit, searchFunction, config = DEFAULT_GEOHASH_CONFIG) {
|
|
34
|
+
// クエリから緯度・経度を抽出
|
|
35
|
+
const { latitude, longitude } = extractCoordinatesFromNearQuery(nearQuery);
|
|
36
|
+
const maxDistance = extractMaxDistanceFromNearQuery(nearQuery);
|
|
37
|
+
const minDistance = extractMinDistanceFromNearQuery(nearQuery);
|
|
38
|
+
let precision = config.searchPrecision;
|
|
39
|
+
let allCandidates = [];
|
|
40
|
+
let iterations = 0;
|
|
41
|
+
// 段階的に精度を緩和しながら検索
|
|
42
|
+
while (allCandidates.length < limit * config.candidateMultiplier &&
|
|
43
|
+
precision >= config.minPrecision &&
|
|
44
|
+
iterations < config.maxIterations) {
|
|
45
|
+
iterations++;
|
|
46
|
+
// 現在の精度でGeoHashを再計算
|
|
47
|
+
const currentGeoHash = encodeGeoHash(latitude, longitude, precision);
|
|
48
|
+
// 隣接する8方向のGeoHashを取得(合計9ブロック)
|
|
49
|
+
const neighborGeoHashes = getNeighborGeoHashes(currentGeoHash);
|
|
50
|
+
// 9ブロック分のGeoHashで並列検索
|
|
51
|
+
const searchPromises = neighborGeoHashes.map((geohash) => searchFunction(geohash));
|
|
52
|
+
const results = await Promise.all(searchPromises);
|
|
53
|
+
const candidates = results.flat();
|
|
54
|
+
// 重複を除外して追加
|
|
55
|
+
for (const candidate of candidates) {
|
|
56
|
+
if (!allCandidates.some((c) => c.id === candidate.id)) {
|
|
57
|
+
allCandidates.push(candidate);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
// 精度を1文字減らす(検索範囲を広げる)
|
|
61
|
+
precision--;
|
|
62
|
+
}
|
|
63
|
+
// 距離計算・フィルタリング・ソート
|
|
64
|
+
const documentsWithDistance = allCandidates
|
|
65
|
+
.map((doc) => {
|
|
66
|
+
// フィールドから地理座標を取得
|
|
67
|
+
const location = doc[fieldName];
|
|
68
|
+
if (!location ||
|
|
69
|
+
typeof location.latitude !== 'number' ||
|
|
70
|
+
typeof location.longitude !== 'number') {
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
// 距離計算
|
|
74
|
+
const distance = calculateDistance(latitude, longitude, location.latitude, location.longitude);
|
|
75
|
+
// 距離フィルタリング
|
|
76
|
+
if (maxDistance !== undefined && distance > maxDistance) {
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
if (minDistance !== undefined && distance < minDistance) {
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
return {
|
|
83
|
+
...doc,
|
|
84
|
+
__distance: distance,
|
|
85
|
+
__geohash: encodeGeoHash(location.latitude, location.longitude, config.searchPrecision),
|
|
86
|
+
};
|
|
87
|
+
})
|
|
88
|
+
.filter((doc) => doc !== null)
|
|
89
|
+
.sort((a, b) => a.__distance - b.__distance)
|
|
90
|
+
.slice(0, limit);
|
|
91
|
+
return {
|
|
92
|
+
documents: documentsWithDistance,
|
|
93
|
+
metadata: {
|
|
94
|
+
iterations,
|
|
95
|
+
candidatesFound: allCandidates.length,
|
|
96
|
+
requestedLimit: limit,
|
|
97
|
+
},
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
//# sourceMappingURL=nearSearch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nearSearch.js","sourceRoot":"","sources":["../../../src/server/query/nearSearch.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generator.d.ts","sourceRoot":"","sources":["../../../src/server/shadow/generator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"generator.d.ts","sourceRoot":"","sources":["../../../src/server/shadow/generator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAY9D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAGhD;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,uBAAuB;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,oBAAoB;IACpB,EAAE,EAAE,MAAM,CAAC;CACZ;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CA2BrD;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAgBtE;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAElD;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAiB7E;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CAE9E;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CAEvE;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,eAAe,EACrB,KAAK,EAAE,OAAO,EACd,MAAM,EAAE,YAAY,GACnB,MAAM,CA6BR;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAE7D;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,YAAY,EAAE,MAAM,EACpB,MAAM,EAAE,YAAY,GACnB,YAAY,EAAE,CA0DhB"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { escapeString as shadowsEscapeString, formatBoolean as shadowsFormatBoolean, formatDatetime as shadowsFormatDatetime, generateMainRecordSK as shadowsGenerateMainRecordSK, } from '../../shadows/index.js';
|
|
2
|
+
import { DEFAULT_GEOHASH_CONFIG, encodeGeoHash, isGeoCoordinates, } from '../../shared/geohash/index.js';
|
|
1
3
|
import { inferFieldType } from './typeInference.js';
|
|
2
|
-
import { escapeString as shadowsEscapeString, formatDatetime as shadowsFormatDatetime, formatBoolean as shadowsFormatBoolean, generateMainRecordSK as shadowsGenerateMainRecordSK, } from '../../shadows/index.js';
|
|
3
4
|
/**
|
|
4
5
|
* JSONオブジェクトのフィールドを正規化
|
|
5
6
|
*
|
|
@@ -240,6 +241,17 @@ export function generateShadowRecords(record, resourceName, config) {
|
|
|
240
241
|
if (value === null || value === undefined) {
|
|
241
242
|
continue;
|
|
242
243
|
}
|
|
244
|
+
// GeoCoordinates型を検出してGeoHashに変換
|
|
245
|
+
if (isGeoCoordinates(value)) {
|
|
246
|
+
const geohash = encodeGeoHash(value.latitude, value.longitude, DEFAULT_GEOHASH_CONFIG.shadowPrecision);
|
|
247
|
+
// GeoHashシャドウキーを生成
|
|
248
|
+
const sk = `${fieldName}#${geohash}#id#${record.id}`;
|
|
249
|
+
shadows.push({
|
|
250
|
+
PK: resourceName,
|
|
251
|
+
SK: sk,
|
|
252
|
+
});
|
|
253
|
+
continue;
|
|
254
|
+
}
|
|
243
255
|
// 型推論
|
|
244
256
|
const type = inferFieldType(value);
|
|
245
257
|
if (!type) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generator.js","sourceRoot":"","sources":["../../../src/server/shadow/generator.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"generator.js","sourceRoot":"","sources":["../../../src/server/shadow/generator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/shared/geohash/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/shared/geohash/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GeoHash関連の型定義
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* 地理座標
|
|
6
|
+
*/
|
|
7
|
+
export interface GeoCoordinates {
|
|
8
|
+
latitude: number;
|
|
9
|
+
longitude: number;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* $near演算子のクエリ(GeoJSON形式)
|
|
13
|
+
*/
|
|
14
|
+
export interface NearQueryGeoJSON {
|
|
15
|
+
$geometry: {
|
|
16
|
+
type: 'Point';
|
|
17
|
+
coordinates: [number, number];
|
|
18
|
+
};
|
|
19
|
+
$maxDistance?: number;
|
|
20
|
+
$minDistance?: number;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* $near演算子のクエリ(簡易形式)
|
|
24
|
+
*/
|
|
25
|
+
export interface NearQuerySimple {
|
|
26
|
+
latitude: number;
|
|
27
|
+
longitude: number;
|
|
28
|
+
maxDistance?: number;
|
|
29
|
+
minDistance?: number;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* $near演算子のクエリ(統合型)
|
|
33
|
+
*/
|
|
34
|
+
export type NearQuery = NearQueryGeoJSON | NearQuerySimple;
|
|
35
|
+
/**
|
|
36
|
+
* 距離付きドキュメント
|
|
37
|
+
*/
|
|
38
|
+
export interface DocumentWithDistance extends Record<string, unknown> {
|
|
39
|
+
__distance?: number;
|
|
40
|
+
__geohash?: string;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* GeoHash設定
|
|
44
|
+
*/
|
|
45
|
+
export interface GeoHashConfig {
|
|
46
|
+
/**
|
|
47
|
+
* シャドウインデックス生成時の精度(デフォルト: 8)
|
|
48
|
+
* ±19m(建物レベル)
|
|
49
|
+
*/
|
|
50
|
+
shadowPrecision: number;
|
|
51
|
+
/**
|
|
52
|
+
* 検索開始時の精度(デフォルト: 6)
|
|
53
|
+
* ±610m(近隣レベル)
|
|
54
|
+
*/
|
|
55
|
+
searchPrecision: number;
|
|
56
|
+
/**
|
|
57
|
+
* 最小精度(段階的検索用、デフォルト: 4)
|
|
58
|
+
* ±20km(大都市レベル)
|
|
59
|
+
*/
|
|
60
|
+
minPrecision: number;
|
|
61
|
+
/**
|
|
62
|
+
* 最大検索反復回数(デフォルト: 5)
|
|
63
|
+
*/
|
|
64
|
+
maxIterations: number;
|
|
65
|
+
/**
|
|
66
|
+
* 候補数の倍率(デフォルト: 3)
|
|
67
|
+
*/
|
|
68
|
+
candidateMultiplier: number;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* GeoHash精度と誤差の対応表
|
|
72
|
+
*/
|
|
73
|
+
export declare const GEOHASH_PRECISION_TABLE: {
|
|
74
|
+
readonly 1: {
|
|
75
|
+
readonly error: 2500000;
|
|
76
|
+
readonly description: "大陸レベル";
|
|
77
|
+
};
|
|
78
|
+
readonly 4: {
|
|
79
|
+
readonly error: 20000;
|
|
80
|
+
readonly description: "大都市レベル";
|
|
81
|
+
};
|
|
82
|
+
readonly 6: {
|
|
83
|
+
readonly error: 610;
|
|
84
|
+
readonly description: "近隣レベル";
|
|
85
|
+
};
|
|
86
|
+
readonly 7: {
|
|
87
|
+
readonly error: 76;
|
|
88
|
+
readonly description: "街区レベル";
|
|
89
|
+
};
|
|
90
|
+
readonly 8: {
|
|
91
|
+
readonly error: 19;
|
|
92
|
+
readonly description: "建物レベル";
|
|
93
|
+
};
|
|
94
|
+
readonly 10: {
|
|
95
|
+
readonly error: 0.6;
|
|
96
|
+
readonly description: "高精度";
|
|
97
|
+
};
|
|
98
|
+
};
|
|
99
|
+
/**
|
|
100
|
+
* デフォルトGeoHash設定
|
|
101
|
+
*/
|
|
102
|
+
export declare const DEFAULT_GEOHASH_CONFIG: GeoHashConfig;
|
|
103
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/shared/geohash/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE;QACT,IAAI,EAAE,OAAO,CAAC;QACd,WAAW,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;KAC/B,CAAC;IACF,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,MAAM,SAAS,GAAG,gBAAgB,GAAG,eAAe,CAAC;AAE3D;;GAEG;AACH,MAAM,WAAW,oBAAqB,SAAQ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IACnE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B;;;OAGG;IACH,eAAe,EAAE,MAAM,CAAC;IAExB;;;OAGG;IACH,eAAe,EAAE,MAAM,CAAC;IAExB;;;OAGG;IACH,YAAY,EAAE,MAAM,CAAC;IAErB;;OAEG;IACH,aAAa,EAAE,MAAM,CAAC;IAEtB;;OAEG;IACH,mBAAmB,EAAE,MAAM,CAAC;CAC7B;AAED;;GAEG;AACH,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;;;CAO1B,CAAC;AAEX;;GAEG;AACH,eAAO,MAAM,sBAAsB,EAAE,aAMpC,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GeoHash関連の型定義
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* GeoHash精度と誤差の対応表
|
|
6
|
+
*/
|
|
7
|
+
export const GEOHASH_PRECISION_TABLE = {
|
|
8
|
+
1: { error: 2500000, description: '大陸レベル' },
|
|
9
|
+
4: { error: 20000, description: '大都市レベル' },
|
|
10
|
+
6: { error: 610, description: '近隣レベル' },
|
|
11
|
+
7: { error: 76, description: '街区レベル' },
|
|
12
|
+
8: { error: 19, description: '建物レベル' },
|
|
13
|
+
10: { error: 0.6, description: '高精度' },
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* デフォルトGeoHash設定
|
|
17
|
+
*/
|
|
18
|
+
export const DEFAULT_GEOHASH_CONFIG = {
|
|
19
|
+
shadowPrecision: 8, // ±19m(建物レベル)
|
|
20
|
+
searchPrecision: 6, // ±610m(近隣レベル)
|
|
21
|
+
minPrecision: 4, // ±20km(大都市レベル)
|
|
22
|
+
maxIterations: 5,
|
|
23
|
+
candidateMultiplier: 3,
|
|
24
|
+
};
|
|
25
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/shared/geohash/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AA8EH;;GAEG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG;IACrC,CAAC,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE;IAC3C,CAAC,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE;IAC1C,CAAC,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,WAAW,EAAE,OAAO,EAAE;IACvC,CAAC,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,WAAW,EAAE,OAAO,EAAE;IACtC,CAAC,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,WAAW,EAAE,OAAO,EAAE;IACtC,EAAE,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,WAAW,EAAE,KAAK,EAAE;CAC9B,CAAC;AAEX;;GAEG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAkB;IACnD,eAAe,EAAE,CAAC,EAAE,cAAc;IAClC,eAAe,EAAE,CAAC,EAAE,eAAe;IACnC,YAAY,EAAE,CAAC,EAAE,gBAAgB;IACjC,aAAa,EAAE,CAAC;IAChB,mBAAmB,EAAE,CAAC;CACvB,CAAC"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import type { GeoCoordinates, NearQuery, NearQueryGeoJSON } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* 地理座標かどうかを判定
|
|
4
|
+
*/
|
|
5
|
+
export declare function isGeoCoordinates(value: unknown): value is GeoCoordinates;
|
|
6
|
+
/**
|
|
7
|
+
* GeoHashエンコード
|
|
8
|
+
* @param latitude 緯度 (-90 to 90)
|
|
9
|
+
* @param longitude 経度 (-180 to 180)
|
|
10
|
+
* @param precision 精度(文字数)デフォルト: 6
|
|
11
|
+
* @returns GeoHash文字列
|
|
12
|
+
*/
|
|
13
|
+
export declare function encodeGeoHash(latitude: number, longitude: number, precision?: number): string;
|
|
14
|
+
/**
|
|
15
|
+
* GeoHashデコード
|
|
16
|
+
* @param geohash GeoHash文字列
|
|
17
|
+
* @returns { latitude, longitude, error }
|
|
18
|
+
*/
|
|
19
|
+
export declare function decodeGeoHash(geohash: string): {
|
|
20
|
+
latitude: number;
|
|
21
|
+
longitude: number;
|
|
22
|
+
error: {
|
|
23
|
+
latitude: number;
|
|
24
|
+
longitude: number;
|
|
25
|
+
};
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* 隣接する8方向のGeoHashを取得
|
|
29
|
+
* @param geohash 中心のGeoHash文字列
|
|
30
|
+
* @returns 9つのGeoHash(中心 + 8方向)
|
|
31
|
+
*/
|
|
32
|
+
export declare function getNeighborGeoHashes(geohash: string): string[];
|
|
33
|
+
/**
|
|
34
|
+
* Haversine公式による2点間の距離計算
|
|
35
|
+
* @param lat1 地点1の緯度
|
|
36
|
+
* @param lon1 地点1の経度
|
|
37
|
+
* @param lat2 地点2の緯度
|
|
38
|
+
* @param lon2 地点2の経度
|
|
39
|
+
* @returns 距離(メートル)
|
|
40
|
+
*/
|
|
41
|
+
export declare function calculateDistance(lat1: number, lon1: number, lat2: number, lon2: number): number;
|
|
42
|
+
/**
|
|
43
|
+
* $nearクエリがGeoJSON形式かどうかを判定
|
|
44
|
+
*/
|
|
45
|
+
export declare function isNearQueryGeoJSON(query: NearQuery): query is NearQueryGeoJSON;
|
|
46
|
+
/**
|
|
47
|
+
* $nearクエリから緯度・経度を抽出
|
|
48
|
+
*/
|
|
49
|
+
export declare function extractCoordinatesFromNearQuery(query: NearQuery): GeoCoordinates;
|
|
50
|
+
/**
|
|
51
|
+
* $nearクエリから最大距離を抽出
|
|
52
|
+
*/
|
|
53
|
+
export declare function extractMaxDistanceFromNearQuery(query: NearQuery): number | undefined;
|
|
54
|
+
/**
|
|
55
|
+
* $nearクエリから最小距離を抽出
|
|
56
|
+
*/
|
|
57
|
+
export declare function extractMinDistanceFromNearQuery(query: NearQuery): number | undefined;
|
|
58
|
+
/**
|
|
59
|
+
* 緯度・経度の範囲チェック
|
|
60
|
+
*/
|
|
61
|
+
export declare function validateLocation(latitude: number, longitude: number): void;
|
|
62
|
+
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/shared/geohash/utils.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,gBAAgB,EAAmB,MAAM,YAAY,CAAC;AAE/F;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,cAAc,CAaxE;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,GAAE,MAAU,GAAG,MAAM,CAEhG;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG;IAC9C,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;CAChD,CAEA;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAe9D;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAahG;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,SAAS,GAAG,KAAK,IAAI,gBAAgB,CAE9E;AAED;;GAEG;AACH,wBAAgB,+BAA+B,CAAC,KAAK,EAAE,SAAS,GAAG,cAAc,CAchF;AAED;;GAEG;AACH,wBAAgB,+BAA+B,CAAC,KAAK,EAAE,SAAS,GAAG,MAAM,GAAG,SAAS,CAMpF;AAED;;GAEG;AACH,wBAAgB,+BAA+B,CAAC,KAAK,EAAE,SAAS,GAAG,MAAM,GAAG,SAAS,CAMpF;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,CAO1E"}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GeoHashユーティリティ関数
|
|
3
|
+
*/
|
|
4
|
+
import ngeohash from 'ngeohash';
|
|
5
|
+
/**
|
|
6
|
+
* 地理座標かどうかを判定
|
|
7
|
+
*/
|
|
8
|
+
export function isGeoCoordinates(value) {
|
|
9
|
+
return (typeof value === 'object' &&
|
|
10
|
+
value !== null &&
|
|
11
|
+
'latitude' in value &&
|
|
12
|
+
'longitude' in value &&
|
|
13
|
+
typeof value.latitude === 'number' &&
|
|
14
|
+
typeof value.longitude === 'number' &&
|
|
15
|
+
value.latitude >= -90 &&
|
|
16
|
+
value.latitude <= 90 &&
|
|
17
|
+
value.longitude >= -180 &&
|
|
18
|
+
value.longitude <= 180);
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* GeoHashエンコード
|
|
22
|
+
* @param latitude 緯度 (-90 to 90)
|
|
23
|
+
* @param longitude 経度 (-180 to 180)
|
|
24
|
+
* @param precision 精度(文字数)デフォルト: 6
|
|
25
|
+
* @returns GeoHash文字列
|
|
26
|
+
*/
|
|
27
|
+
export function encodeGeoHash(latitude, longitude, precision = 6) {
|
|
28
|
+
return ngeohash.encode(latitude, longitude, precision);
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* GeoHashデコード
|
|
32
|
+
* @param geohash GeoHash文字列
|
|
33
|
+
* @returns { latitude, longitude, error }
|
|
34
|
+
*/
|
|
35
|
+
export function decodeGeoHash(geohash) {
|
|
36
|
+
return ngeohash.decode(geohash);
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* 隣接する8方向のGeoHashを取得
|
|
40
|
+
* @param geohash 中心のGeoHash文字列
|
|
41
|
+
* @returns 9つのGeoHash(中心 + 8方向)
|
|
42
|
+
*/
|
|
43
|
+
export function getNeighborGeoHashes(geohash) {
|
|
44
|
+
const neighbors = [
|
|
45
|
+
geohash, // 中心
|
|
46
|
+
ngeohash.neighbor(geohash, [1, 0]), // 右
|
|
47
|
+
ngeohash.neighbor(geohash, [-1, 0]), // 左
|
|
48
|
+
ngeohash.neighbor(geohash, [0, 1]), // 上
|
|
49
|
+
ngeohash.neighbor(geohash, [0, -1]), // 下
|
|
50
|
+
ngeohash.neighbor(geohash, [1, 1]), // 右上
|
|
51
|
+
ngeohash.neighbor(geohash, [1, -1]), // 右下
|
|
52
|
+
ngeohash.neighbor(geohash, [-1, 1]), // 左上
|
|
53
|
+
ngeohash.neighbor(geohash, [-1, -1]), // 左下
|
|
54
|
+
];
|
|
55
|
+
// 重複を排除(境界条件で同じGeoHashが返る場合がある)
|
|
56
|
+
return Array.from(new Set(neighbors));
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Haversine公式による2点間の距離計算
|
|
60
|
+
* @param lat1 地点1の緯度
|
|
61
|
+
* @param lon1 地点1の経度
|
|
62
|
+
* @param lat2 地点2の緯度
|
|
63
|
+
* @param lon2 地点2の経度
|
|
64
|
+
* @returns 距離(メートル)
|
|
65
|
+
*/
|
|
66
|
+
export function calculateDistance(lat1, lon1, lat2, lon2) {
|
|
67
|
+
const R = 6371000; // 地球の半径(メートル)
|
|
68
|
+
const φ1 = (lat1 * Math.PI) / 180;
|
|
69
|
+
const φ2 = (lat2 * Math.PI) / 180;
|
|
70
|
+
const Δφ = ((lat2 - lat1) * Math.PI) / 180;
|
|
71
|
+
const Δλ = ((lon2 - lon1) * Math.PI) / 180;
|
|
72
|
+
const a = Math.sin(Δφ / 2) * Math.sin(Δφ / 2) +
|
|
73
|
+
Math.cos(φ1) * Math.cos(φ2) * Math.sin(Δλ / 2) * Math.sin(Δλ / 2);
|
|
74
|
+
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
|
|
75
|
+
return R * c;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* $nearクエリがGeoJSON形式かどうかを判定
|
|
79
|
+
*/
|
|
80
|
+
export function isNearQueryGeoJSON(query) {
|
|
81
|
+
return '$geometry' in query && query.$geometry.type === 'Point';
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* $nearクエリから緯度・経度を抽出
|
|
85
|
+
*/
|
|
86
|
+
export function extractCoordinatesFromNearQuery(query) {
|
|
87
|
+
if (isNearQueryGeoJSON(query)) {
|
|
88
|
+
// GeoJSON形式: coordinates = [経度, 緯度]
|
|
89
|
+
return {
|
|
90
|
+
longitude: query.$geometry.coordinates[0],
|
|
91
|
+
latitude: query.$geometry.coordinates[1],
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
// 簡易形式
|
|
96
|
+
return {
|
|
97
|
+
latitude: query.latitude,
|
|
98
|
+
longitude: query.longitude,
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* $nearクエリから最大距離を抽出
|
|
104
|
+
*/
|
|
105
|
+
export function extractMaxDistanceFromNearQuery(query) {
|
|
106
|
+
if (isNearQueryGeoJSON(query)) {
|
|
107
|
+
return query.$maxDistance;
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
return query.maxDistance;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* $nearクエリから最小距離を抽出
|
|
115
|
+
*/
|
|
116
|
+
export function extractMinDistanceFromNearQuery(query) {
|
|
117
|
+
if (isNearQueryGeoJSON(query)) {
|
|
118
|
+
return query.$minDistance;
|
|
119
|
+
}
|
|
120
|
+
else {
|
|
121
|
+
return query.minDistance;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* 緯度・経度の範囲チェック
|
|
126
|
+
*/
|
|
127
|
+
export function validateLocation(latitude, longitude) {
|
|
128
|
+
if (latitude < -90 || latitude > 90) {
|
|
129
|
+
throw new Error('Latitude must be between -90 and 90');
|
|
130
|
+
}
|
|
131
|
+
if (longitude < -180 || longitude > 180) {
|
|
132
|
+
throw new Error('Longitude must be between -180 and 180');
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../src/shared/geohash/utils.ts"],"names":[],"mappings":"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"}
|
package/dist/shared/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/shared/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,cAAc,kBAAkB,CAAC;AAGjC,cAAc,mBAAmB,CAAC;AAGlC,cAAc,kBAAkB,CAAC;AAGjC,cAAc,sBAAsB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/shared/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,cAAc,kBAAkB,CAAC;AAGjC,cAAc,mBAAmB,CAAC;AAGlC,cAAc,kBAAkB,CAAC;AAGjC,cAAc,sBAAsB,CAAC;AAGrC,cAAc,oBAAoB,CAAC"}
|
package/dist/shared/index.js
CHANGED
package/dist/shared/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/shared/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM;AACN,cAAc,kBAAkB,CAAC;AAEjC,SAAS;AACT,cAAc,mBAAmB,CAAC;AAElC,UAAU;AACV,cAAc,kBAAkB,CAAC;AAEjC,KAAK;AACL,cAAc,sBAAsB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/shared/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM;AACN,cAAc,kBAAkB,CAAC;AAEjC,SAAS;AACT,cAAc,mBAAmB,CAAC;AAElC,UAAU;AACV,cAAc,kBAAkB,CAAC;AAEjC,KAAK;AACL,cAAc,sBAAsB,CAAC;AAErC,eAAe;AACf,cAAc,oBAAoB,CAAC"}
|