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 Record
s 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?