如果位置坐标在猫鼬中给定的$geoWithin或$geoNear半径内,如何获得布尔值



我想得到一个布尔值,例如,如果位置坐标在给定半径内,则为true或false。这是mongoose聚合函数中的$geoWithin查询或$geoNear管道。如果我在mongoose聚合管道中使用$geoNear,那么它只返回过滤后的结果。到目前为止,我已经做了以下工作,

型号:

import * as mongoose from 'mongoose';
import { User } from 'src/user/user.model';
export const BlipSchema = new mongoose.Schema(
{
user: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User',
},
media: [
new mongoose.Schema(
{
fileName: String,
mediaType: {
type: String,
enum: ['image', 'video'],
},
},
{
toJSON: {
transform: function (doc, ret) {
delete ret._id;
},
},
},
),
],
likesCount: {
type: Number,
default: 0,
},
commentsCount: {
type: Number,
default: 0,
},
isLiked: Boolean,
status: {
type: String,
enum: ['public', 'private'],
default: 'public',
},
location: {
type: {
type: String,
default: 'Point',
enum: ['Point'],
},
coordinates: [Number],
address: String,
description: String,
},
lat: Number,
lng: Number,
address: String,
city: {
type: String,
default: '',
},
createdAt: {
type: Date,
default: Date.now,
},
},
{
toJSON: {
transform: function (doc, ret) {
ret.id = ret._id;
delete ret._id;
delete ret.location;
delete ret.__v;
},
},
toObject: { virtuals: true },
},
);
export interface Media {
fileName: string;
mediaType: string;
}
export interface Location {
type: string;
coordinates: [number];
address: string;
description: string;
}
export interface Blip {
user: User;
media: [Media];
likesCount: number;
commentsCount: number;
isLiked: boolean;
status: string;
lat: number;
lng: number;
address: string;
city: string;
createdAt: string;
}

我的控制器中的功能:

async getLocationBlips(user: User, query: any) {
const aggrea = [];
aggrea.push(
{
$lookup: {
from: 'users',
localField: 'user',
foreignField: '_id',
as: 'user',
},
},
{
$unwind: '$user',
},
{ $set: { 'user.id': '$user._id' } },
{
$group: {
_id: { lat: '$lat', lng: '$lng' },
lat: { $first: '$lat' },
lng: { $first: '$lng' },
isViewable: { $first: false },
totalBlips: { $sum: 1 },
blips: {
$push: {
id: '$_id',
media: '$media',
user: '$user',
likesCount: '$likesCount',
commentsCount: '$commentsCount',
isLiked: '$isLiked',
status: '$status',
address: '$address',
city: '$city',
createdAt: '$createdAt',
},
},
},
},
{ $unset: 'blips.media._id' },
{ $unset: 'blips.user._id' },
{ $unset: 'blips.user.__v' },
{
$project: {
_id: 0,
lat: 1,
lng: 1,
totalBlips: 1,
isViewable: 1,
blips: 1,
},
},
{ $sort: { totalBlips: -1 } },
);
if (query.page !== undefined && query.limit !== undefined) {
const page = query.page * 1;
const limit = query.limit * 1;
const skip = (page - 1) * limit;
aggrea.push({ $skip: skip }, { $limit: parseInt(query.limit, 10) });
}
const blipLocations = await this.blipModel.aggregate(aggrea);
const total = blipLocations.length;
let viewableBlips = [];
if (query.lat && query.lng) {
const radius = query.distance / 3963.2;
viewableBlips = await this.blipModel.find({
location: {
$geoWithin: {
$centerSphere: [[query.lng, query.lat], radius],
},
},
});
}
await Promise.all(
blipLocations.map(async (blpL) => {
await Promise.all(
blpL.blips.map(async (blp) => {
const like = await this.likeModel.findOne({
user: user.id,
blip: blp.id,
});
if (like) {
blp.isLiked = true;
} else {
blp.isLiked = false;
}
if (query.lat && query.lng) {
viewableBlips.forEach((vBlp) => {
if (vBlp._id.toString() === blp.id.toString()) {
console.log(vBlp.id);
blpL.isViewable = true;
}
});
}
}),
);
}),
);
return {
status: true,
message: 'Data fetched successfully',
results: total,
blipLocations,
};
}

在上面的片段中,我有一个名为isViewable的字段。现在我正在运行时更新此字段。但我想在聚合管道中更新此字段。是否有任何方法可以检查位置坐标是否在聚合管道提供的$geoWithin或$geoNear内?谢谢

如果您可以使用$geoNear(您需要2dsphere索引,它必须是文档中提到的管道中的第一阶段(,您可以添加一个距离字段,然后添加另一个字段,该字段将基于它输出布尔值,如下所示:

this.blipModel.aggregate([
{
$geoNear: {
key: 'location',
near: {
type: 'Point',
coordinates: [query.lng, query.lat]
},
distanceField: 'distance',
spherical: true
}
}, 
{
$addFields: {
isViewable: {
$cond: {
if: {$lte: ["$distance", query.distance]},
then: true,
else: false
}
}
}
}
]);

如果你不需要,可以选择在另一个阶段取消设置距离字段。

最新更新