如何在NestJS+TypeORM+MongoDB实体中定义Location字段
Alright, I've been in your shoes before—moving from Mongoose to TypeORM with MongoDB and needing to replicate those GeoJSON structures can feel a bit tricky at first. Let's get your Location field set up properly, matching exactly what you had with Mongoose, no Mongoose required.
First, you'll need to use TypeORM's @Index decorator to set up the 2dsphere spatial index, and define your Location as a nested object column. Here's the updated BootcampEntity code with the Location field implemented:
import { BaseEntity, Entity, PrimaryGeneratedColumn, Column, ObjectID, ObjectIdColumn, Index } from 'typeorm'; import { IsNotEmpty, MaxLength } from 'class-validator'; @Entity('bootcamp') export class BootcampEntity extends BaseEntity { @ObjectIdColumn() id: ObjectID; @Column({type:'text',unique:true,length:50,nullable: false}) name:string; @Column({type:'text'}) slug: string; @Column({type:'text',length:500,nullable: false}) description: string; @Column({type:'text'}) website: string; @Column({type:'text',length:20}) phone: string; @Column({type:'text',}) email: string; @Column({type:'text',nullable: false}) address: string; @Column({type:'text',array: true }) careers: string[]; @Column({type:'int'}) averageRating:number @Column({type:'int'}) averageCost:number @Column({type:'string',default:'no-photo.jpg'}) photo: string; @Column({type:'boolean',default:false}) housing: boolean; @Column({type:'boolean',default:false}) jobAssistance: boolean; @Column({type:'boolean',default:false}) jobGuarantee: boolean; @Column({type:'boolean',default:false}) acceptGi: boolean; @Column({type:'date',default:Date.now()}) createdAt: Date; // Replicated Location field matching Mongoose structure @Index({ spatial: true, spatialType: '2dsphere' }) @Column({ type: 'object', nullable: false, default: () => ({ type: 'Point', coordinates: [], formattedAddress: '', street: '', city: '', state: '', zipcode: '', country: '' }) }) location: { type: 'Point'; // Matches Mongoose's enum: ['Point'] constraint coordinates: [number, number]; // Longitude first, latitude second (GeoJSON standard) formattedAddress: string; street: string; city: string; state: string; zipcode: string; country: string; }; }
Key Details Explained:
- Spatial Index: The
@Index({ spatial: true, spatialType: '2dsphere' })decorator creates the exact same 2dsphere index you had in Mongoose, enabling geospatial queries later on. - Nested Object Column: Setting
type: 'object'in@Columntells TypeORM this is a nested MongoDB document, just like your Mongooselocationobject. - Type Constraint: The
type: 'Point'in the location structure enforces the GeoJSON Point type, matching Mongoose'senum: ['Point']to ensure consistency. - Default Values: The
defaultoption initializes the location object with empty values (similar to how Mongoose would handle uninitialized fields), so you don't have to worry about nulls unless you explicitly want them.
Once you've updated the entity, run your TypeORM migration or schema sync, and your MongoDB collection will have the location field with the correct structure and 2dsphere index—exactly what you had with Mongoose, but using pure TypeORM.
内容的提问来源于stack exchange,提问作者user12130378

