node.js - 存储 GeoJson 点并在给定距离/半径内查找点 | NODEJS、Postgres、NestJs、TypeOrm

标签 node.js postgresql nestjs geojson 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

测试位置.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
}

位置.服务.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);
  }
}


Post Request Database Geometry view Get Request Range

关于node.js - 存储 GeoJson 点并在给定距离/半径内查找点 | NODEJS、Postgres、NestJs、TypeOrm,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67435650/

相关文章:

javascript - 无法在 React 中将数据发布到 mlab

NestJS - 如何在 NestJS 托管类之外使用 ConfigService?

javascript - 将特定值注入(inject)对象构造函数

javascript - zombie JS : intermittently crashes when called repeatedly from a for loop

node.js - 在带有nodejs的azure函数应用程序中使用SSL证书

javascript - 为什么我不能用 Mongoose 设置数据库?

ruby-on-rails - 如何按散列值在 JSON 散列数组中进行搜索?

python - 不能 "install"plpython3u - postgresql

postgresql - 所选的 LC_CTYPE 设置需要编码 "LATIN1"

unit-testing - NestJs 对 typeorm 分页进行单元测试时出现错误 queryBuilder.take(...).skip 不是函数