存储 GeoJson 点并在给定距离/半径内查找点 | NODEJS、Postgres、NestJs、TypeOrm
Posted
技术标签:
【中文标题】存储 GeoJson 点并在给定距离/半径内查找点 | NODEJS、Postgres、NestJs、TypeOrm【英文标题】:Storing GeoJson points and finding points within a given distance/radius | NODEJS, Postgres, NestJs, TypeOrm 【发布时间】:2021-07-29 19:17:03 【问题描述】:提前谢谢你。 我已经在互联网上搜索了一个工作示例/文档,用于存储位置点(经度、纬度)、查找两点之间的距离、查找给定距离内的点。 我正在使用 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 数据类型,因为它的速度较慢。
【问题讨论】:
【参考方案1】:以下代码将存储在数据库中并查找范围内的位置
技术栈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);
【讨论】:
非常感谢@Pradeep 我在 6 天前就知道了:这是我的笔记:hussainwali.medium.com/… 收到此错误:QueryFailedError: type "geography" does not exist
可能是什么原因?
TestLocation 中为什么有 lat、long 和一个 Point,这个 Point 就足够了吗?
是的,点就够了。出于调试目的,我保留了它。以上是关于存储 GeoJson 点并在给定距离/半径内查找点 | NODEJS、Postgres、NestJs、TypeOrm的主要内容,如果未能解决你的问题,请参考以下文章