Search code examples
postgresqlnestjspostgisgeojsontypeorm

How can I send GeoJSON polygon data into typeorm (NestJS)?


I want to send GeoJSON polygon data into PostgresSQL by POST request.

Therefore, I have tried to receive Position[][] type and convert it into a Polygon type then send a POST request by Postman for API test but I got an error: "QueryFailedError: Unable to find 'coordinates' in GeoJSON string".

There are my codes:

  • Entity

     import { Column, Entity, Index, PrimaryGeneratedColumn } from "typeorm";
     import { Polygon } from "geojson";
    
     @Entity({ name: 'parcels' })
     export class Parcel {
    
         @PrimaryGeneratedColumn('uuid')
         id: string
    
         @Index({ spatial: true })
         @Column({
             type: 'geography',
             spatialFeatureType: 'Polygon',
             srid:4326,
             nullable: true
         })
         polygon: Polygon
    
     }
    
  • Dto

     import { IsOptional } from "class-validator";
     import { Position } from "geojson";
    
     export class CreateParcelPointDto { 
         @IsOptional()
         position?: Position[][]
     }
    
  • Controller

     import { Body, Controller, Post } from '@nestjs/common';
     import { CreateParcelPointDto } from './dto/create-parcel-point.dto';
     import { Parcel } from './parcel.entity';
     import { ParcelService } from './parcel.service';
    
     @Controller('parcels')
     export class ParcelController {
         constructor(private parcelService: ParcelService) {}
    
         @Post()
         async createParcelPoint(
             @Body()
             createParcelPointDto: CreateParcelPointDto
         ): Promise<Parcel> {
             return this.parcelService.createParcelPoint(createParcelPointDto)
         }
     }
    
  • Service

     import { Injectable } from '@nestjs/common';
     import { InjectRepository } from '@nestjs/typeorm';
     import { Polygon } from 'geojson';
     import { CreateParcelPointDto } from './dto/create-parcel-point.dto';
     import { ParcelRepository } from './parcel.repository';
     import { Parcel } from './parcel.entity';
    
     @Injectable()
     export class ParcelService {
         constructor(
             @InjectRepository(ParcelRepository)
             private parcelRepository: ParcelRepository
         ) {}
    
         async createParcelPoint(createParcelPointDto: CreateParcelPointDto): Promise<Parcel> {
             const { position } = createParcelPointDto
    
             const polygon: Polygon = {
                 type: 'Polygon',
                 coordinates: position
             }
    
             const parcel = this.parcelRepository.create({
                 polygon,
             })
    
             await this.parcelRepository.save(parcel)
             return parcel
         }
     }
    
  • POST request JSON

      {
          "polygon" : [
              [ 102.016680916961207, 14.876721809875564 ], 
              [ 102.016926580451127, 14.876676829236565 ], 
              [ 102.016936960598585, 14.876688939408604 ], 
              [ 102.017125533277465, 14.876656068941644 ], 
              [ 102.017130723351187, 14.876638768695875 ], 
              [ 102.017360816619913, 14.876598978130607 ], 
              [ 102.017243174948689, 14.87595713901259 ], 
              [ 102.017000971507926, 14.876002119651588 ], 
              [ 102.016994051409625, 14.875983089381243 ], 
              [ 102.016789908509551, 14.876022879946511 ], 
              [ 102.016786448460394, 14.876047100290586 ], 
              [ 102.016559815240825, 14.876090350905008 ], 
              [ 102.016680916961207, 14.876721809875564 ]
          ],
      }
    

I don't know how to handle GeoJSON type into typeorm by POST request. If anyone has some solution please help me.


Solution

  • I had solved the problem. In this case, you need to define the type in Dto as the number. The dimension must be the same as the Position type and increase one more dimension in coordinates while you create a Polygon object.

    For example, a Polygon type is needed to receive coordinate in Position[][]. Therefore, You need to define polygon as type number[][] in Dto and define coordinates as [polygon] while you create Polygon objects.

    Code example :

    • Dto

       import { IsOptional } from "class-validator";
      
       export class CreateParcelPointDto {
           @IsOptional()
           polygon?: number[][]
       }
      
    • Service

       import { Injectable } from '@nestjs/common';
       import { InjectRepository } from '@nestjs/typeorm';
       import { Polygon } from 'geojson';
       import { CreateParcelPointDto } from './dto/create-parcel-point.dto';
       import { ParcelRepository } from './parcel.repository';
       import { Parcel } from './parcel.entity';
      
       @Injectable()
       export class ParcelService {
           constructor(
               @InjectRepository(ParcelRepository)
               private parcelRepository: ParcelRepository
           ) {}
      
           async createParcelPoint(createParcelPointDto: CreateParcelPointDto): Promise<Parcel> {
               const {
                   polygon,
               } = createParcelPointDto
      
               const polygonCreated: Polygon = {
                   type: 'Polygon',
                   coordinates: [polygon] //Need one more dimension here.
               }
      
               const parcel = this.parcelRepository.create({
                   polygon: polygonCreated,
               })
      
               await this.parcelRepository.save(parcel)
               return parcel
           }
       }