0

In my collection records I have documents with such structure:

@Schema()
export class Record {
  @Prop()
  title: string;

  @Prop()
  lat: number;

  @Prop()
  lon: number;
}
const RecordSchema = SchemaFactory.createForClass(Record);
RecordSchema.index({ location: '2dsphere' }); // <- must be a physical property i guess?
export { RecordSchema };

lat and lon fields are for the latitude and the longitude of the object respectively. I want to retrieve all Records that are closer than radius metres from point with coordinates (userLat;userLon). However, I really do not want to store Record's latitude and longitude in location field (like {title: "test", location: {type: "Point", coordinates: [50, 80]}}, though it works).

I created a virtual location on my schema:

RecordSchema.virtual('location').get(function (this: RecordDocument) {
  return {
    type: 'Point',
    coordinates: [this.lon, this.lat],
  };
});

And tried to query over it:

async findAll(params: FindRecordsQueryParams): Promise<FindAllResultDto[]> {
  const { userLat, userLon, radius } = params;
  const aggregation: PipelineStage[] = [
    {
      $geoNear: {
        near: {
          type: 'Point',
          coordinates: [userLon, userLat],
        },
        distanceField: 'distance',
        maxDistance: radius,
        spherical: true,
        key: 'location',
      },
    },
  ];
  return this.recordModel.aggregate(aggregation).exec();
}

However, this always returns empty list. So is there a way to perform a geospatial query over a virtual field or any other way to avoid storing lat and lon in GeoJSON Point format?

lavrent
  • 66
  • 1
  • 5

0 Answers0