node.js - 存储 GeoJson 点并在给定距离/半径内查找点 | NODEJS、Postgres、NestJs、TypeOrm
问题描述
先感谢您。我已经在互联网上搜索了一个工作示例/文档,用于存储位置点(经度、纬度)、查找两点之间的距离、查找给定距离内的点。我正在使用 typeorm、nestjs、postgresql。
(我已经尝试过 Mariadb,但 St_distance_sphere 没有在那里工作,所以我使用 postgresql)
这是我的实体
@ApiProperty({
type: String,
title: 'current_location',
example: '{"type":"Point","coordinates":[28.612849, 77.229883]}',
})
@Index({ spatial: true })
@Column({
type: 'geometry',
srid: 4326,
nullable: true,
spatialFeatureType: 'Point',
transformer: {
to: (v: Point) => {
console.log(JSON.stringify(v));
return eval(`ST_GeomFromGeoJSON(${JSON.stringify(v)})`);
},
from: (v: any) => {
return { type: 'Point', coordinates: [v.x, v.y] } as Point;
},
},
})
current_location: string;
似乎有太多的 postgres/postgis 文档,但对我的情况没有任何用处。任何帮助深表感谢。我已经坚持了一个多星期。
*注意:我不想使用 JSONB 数据类型,因为它的速度较慢。
解决方案
以下代码将存储在数据库中并查找范围内的位置
技术栈nestJS,typeorm,postgres,postgis extension,@types/geojson
testlocation.entity.ts
import { Column, Entity, Index, PrimaryGeneratedColumn} from 'typeorm';
import { Geometry, Point } from 'geojson';
@Entity({ name: 't_test_location' })
export class TestLocation {
@PrimaryGeneratedColumn('increment')
pk_id: number;
@Column({ type: 'varchar', name: 's_city' })
city: string;
@Column({ type: 'double precision', name: 'd_lat' })
lat: number;
@Column({ type: 'double precision', name: 'd_long' })
long: number;
@Index({ spatial: true })
@Column({
type: 'geography',
spatialFeatureType: 'Point',
srid: 4326,
nullable: true,
})
location:Point
}
location.service.ts
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { TestLocation } from 'src/model/testlocation.entity';
import { getManager, QueryBuilder, Repository } from 'typeorm';
import { Geometry, Point } from 'geojson';
@Injectable()
export class LocationService {
constructor(
@InjectRepository(TestLocation) private readonly repo: Repository<TestLocation>,
) {}
public async getAll() {
return await this.repo.find();
}
public async create(location:TestLocation){
const pointObject :Point= {
type: "Point",
coordinates: [location.long,location.lat]
};
location.location = pointObject;
return await this.repo.save(location)
}
public async getRange(lat:number,long:number,range:number = 1000) {
let origin = {
type: "Point",
coordinates: [long, lat]
};
let locations = await this.repo
.createQueryBuilder('t_test_location')
.select(['t_test_location.city AS city','ST_Distance(location, ST_SetSRID(ST_GeomFromGeoJSON(:origin), ST_SRID(location)))/1000 AS distance' ])
.where("ST_DWithin(location, ST_SetSRID(ST_GeomFromGeoJSON(:origin), ST_SRID(location)) ,:range)")
.orderBy("distance","ASC")
.setParameters({
// stringify GeoJSON
origin: JSON.stringify(origin),
range:range*1000 //KM conversion
})
.getRawMany();
return locations;
}
}
location.controller.ts
import { Body, Controller, Get, Post } from '@nestjs/common';
import { TestLocation } from 'src/model/testlocation.entity';
import { LocationService } from './location.service';
@Controller('location')
export class LocationController {
constructor(private serv: LocationService) {}
@Get()
public async getAll() {
return await this.serv.getAll();
}
@Post()
createLocation(@Body() location : TestLocation): void{
this.serv.create(location);
}
@Post('range')
public async getRange(@Body() location : {
lat:number,
long:number,
range:number
}){
return await this.serv.getRange(location.lat,location.long,location.range);
}
}
推荐阅读
- javascript - 简单的基于文本的游戏更新文本有问题
- machine-learning - 使用 joblib.dump 保存模型文件后,是否可以获得模型中使用的特征/变量列表?
- c# - 如何将表达式树与具有空选项的对象一起应用
- javascript - 使用 CSS 选择器调用 Javascript
- reactjs - 如何使用扩展运算符更新 React js 中的状态?
- sed - 使用具有多个同名键的 sed 替换 yml 文件的内容
- excel - 将 Office.js(Excel 加载项)连接到 SQL Server
- sql - 如何修复与两个条件匹配的记录的此查询?
- php - PHP7 为所有标准 php 函数添加斜线 php-cs-fixer 规则
- php - Eloquent Collection contains() 有效,但 diff() 或 intersect() 认为一切都不一样