要检索的文档是具有一定范围(整数值)的导师,该范围对应于他们将移动多远。举例来说,如果客户在巴黎48街de Varenne找一位导师,我们应该只检索可以前往巴黎48 rue de Varenne的导师(搜索位置与导师位置必须小于导师范围)
您知道该怎么做吗?查询的是经度和纬度(位置),导师还具有位置(纬度和经度)和范围(他能走多远)。
这是导师模型的简化版本:
import mongoose from 'mongoose';
import validate from 'mongoose-validator';
import { User } from './user';
import mongooseAggregatePaginate from 'mongoose-aggregate-paginate';
var ObjectId = mongoose.Schema.Types.ObjectId;
var tutorSchema = mongoose.Schema({
location: {
address_components: [
{
long_name: String,
short_name: String,
types: String
}
],
description: String,
lat: Number,
lng: Number
},
range: {
type: Number,
default: 15
},
loc: {
type: { type: String },
coordinates: []
}
});
tutorSchema.plugin(mongooseAggregatePaginate);
tutorSchema.index({ "loc": "2dsphere" });
module.exports = {
Tutor
};
这是我到目前为止的查询(不考虑范围, lon1和lat1是查询参数):
exports.search = (req, res) => {
let lat1 = req.body.lat;
let lon1 = req.body.lng;
let page = req.body.page || 1;
let perPage = req.body.perPage || 10;
let radius = req.body.radius || 10000;
let levelsIn = req.body.levels && req.body.levels.length !== 0 ? req.body.levels.map(level => {
return ObjectID(level);
}) : null;
let subjectsIn = req.body.subjects && req.body.subjects.length !== 0 ? req.body.subjects.map(subject => {
return ObjectID(subject);
}) : null;
var options = { page: page, limit: perPage, sortBy: { updatedDate: -1 } }
const isAdmin = req.user ? req.user.role === "admin" || req.user.role === "super-admin" : false;
let match = {}
if (levelsIn) match.levels = { $in: levelsIn };
if (subjectsIn) match.subjects = { $in: subjectsIn }
if (typeof req.body.activated !== "undefined") match.profileActivated = req.body.activated;
if (req.body.from) match.createdAt = { $gte: new Date(req.body.from) };
if (req.body.to) {
if (match.createdAt) match.createdAt.$lte = new Date(req.body.to);
else match.createdAt = { $lte: new Date(req.body.to) };
}
var aggregate = null;
if (!isAdmin) {
match.activated = true
match.profileActivated = true
match.profileOnline = true
}
if (lat1 && lon1) {
match.$expr = {
$lt: ["$distance", "$range"] // "calculated_distance < tutor_range"
}
aggregate = Tutor.aggregate([
{
"$geoNear": {
"near": {
"type": "Point",
"coordinates": [lon1, lat1]
},
"distanceField": "distance", // this calculated distance will be compared in next section
"distanceMultiplier": 0.001,
"spherical": true
}
},
{
$match: match
}
]);
} else {
aggregate = Tutor.aggregate([
{
$match: match
}
]);
}
Tutor
.aggregatePaginate(aggregate, options, function (err, result, pageCount, count) {
if (err) {
return res.status(400).send(err);
}
else {
var opts = [
{ path: 'levels', select: 'name' },
{ path: 'subjects', select: 'name' },
{ path: 'assos', select: 'name' }
];
Tutor
.populate(result, opts)
.then(result2 => {
return res.send({
page: page,
perPage: perPage,
pageCount: pageCount,
documentCount: count,
tutors: result2
});
})
.catch(err => {
return res.status(400).send(err);
});
}
})
};
谢谢您的帮助!
答案 0 :(得分:1)
您只需要在管道中添加一个过滤器,以比较 create_table :doctor_locations do |t|
t.integer :doctor_profile_id
t.integer :location_id
t.text :uuid
t.timestamps null: false
end
create_table :locations do |t|
t.string :address
t.integer :ordinal, :default => 1
t.integer :doctor_profile_id
t.text :uuid
t.timestamps
end
add_column :locations, :confidence, :integer
和distance
字段:
range
完整查询:
{
$match: {
$expr: {
$lt: ["$distance", "$range"] // "calculated_distance < tutor_range"
}
}
}