Node.js Mongoose MongoDB地理空间查询
我有一个Node.js Mongoose MongoDB地理空间查询,node.js,mongodb,mongoose,mongodb-query,aggregation-framework,Node.js,Mongodb,Mongoose,Mongodb Query,Aggregation Framework,我有一个项目集合,可以容纳数千到几十万个文档。在该集合上,我希望执行地理空间查询。使用Mongoose,有两个选项-find()和聚合管道。我已经在下面展示了我的两个实现: 猫鼬模型 首先,以下是我的猫鼬模型的相关属性: // Define the schema const itemSchema = new mongoose.Schema({ // Firebase UID (in addition to the Mongo ObjectID) owner: {
项目
集合,可以容纳数千到几十万个文档。在该集合上,我希望执行地理空间查询。使用Mongoose,有两个选项-find()
和聚合管道。我已经在下面展示了我的两个实现:
猫鼬模型
首先,以下是我的猫鼬模型的相关属性:
// Define the schema
const itemSchema = new mongoose.Schema({
// Firebase UID (in addition to the Mongo ObjectID)
owner: {
type: String,
required: true,
ref: 'User'
},
// ... Some more fields
numberOfViews: {
type: Number,
required: true,
default: 0
},
numberOfLikes: {
type: Number,
required: true,
default: 0
},
location: {
type: {
type: 'String',
default: 'Point',
required: true
},
coordinates: {
type: [Number],
required: true,
},
}
}, {
timestamps: true
});
// 2dsphere index
itemSchema.index({ "location": "2dsphere" });
// Create the model
const Item = mongoose.model('Item', itemSchema);
查找查询
聚合管道
假设需要计算的距离:
// These variables are populated based on URL Query Parameters.
const query = {};
const sort = {};
const geoSpatialQuery = {
$geoNear: {
near: {
type: 'Point',
coordinates: [parseInt(req.query.lng), parseInt(req.query.lat)]
},
distanceField: "distance",
maxDistance: parseInt(req.query.maxDistance),
query,
spherical: true
}
};
const items = await Item.aggregate([
geoSpatialQuery,
{ $limit: parseInt(req.query.limit) },
{ $skip: parseInt(req.query.skip) },
{ $sort: { distance: -1, ...sort } }
]).exec();
res.send(items);
编辑-示例文件已修改
下面是一个文档的示例,其中包含项
集合中的所有属性:
{
"_id":"5cd08927c19d1dd118d39a2b",
"imagePaths":{
"standard":{
"images":[
"users/zbYmcwsGhcU3LwROLWa4eC0RRgG3/5cd08927c19d1dd118d39a2b/images/Image-aafe69c7-f93e-411e-b75d-319042068921-standard.jpg",
"users/zbYmcwsGhcU3LwROLWa4eC0RRgG3/5cd08927c19d1dd118d39a2b/images/Image-397c95c6-fb10-4005-b511-692f991341fb-standard.jpg",
"users/zbYmcwsGhcU3LwROLWa4eC0RRgG3/5cd08927c19d1dd118d39a2b/images/Image-e54db72e-7613-433d-8d9b-8d2347440204-standard.jpg",
"users/zbYmcwsGhcU3LwROLWa4eC0RRgG3/5cd08927c19d1dd118d39a2b/images/Image-c767f54f-7d1e-4737-b0e7-c02ee5d8f1cf-standard.jpg"
],
"profile":"users/zbYmcwsGhcU3LwROLWa4eC0RRgG3/5cd08927c19d1dd118d39a2b/images/Image-51318c32-38dc-44ac-aac3-c8cc46698cfa-standard-profile.jpg"
},
"thumbnail":"users/zbYmcwsGhcU3LwROLWa4eC0RRgG3/5cd08927c19d1dd118d39a2b/images/Image-51318c32-38dc-44ac-aac3-c8cc46698cfa-thumbnail.jpg",
"medium":"users/zbYmcwsGhcU3LwROLWa4eC0RRgG3/5cd08927c19d1dd118d39a2b/images/Image-51318c32-38dc-44ac-aac3-c8cc46698cfa-medium.jpg"
},
"location":{
"type":"Point",
"coordinates":[
-110.8571443,
35.4586858
]
},
"numberOfViews":0,
"numberOfLikes":0,
"monetarySellingAmount":9000,
"exchangeCategories":[
"Math"
],
"itemCategories":[
"Sports"
],
"title":"My title",
"itemDescription":"A description",
"exchangeRadius":10,
"owner":"zbYmcwsGhcU3LwROLWa4eC0RRgG3",
"reports":[],
"createdAt":"2019-05-06T19:21:13.217Z",
"updatedAt":"2019-05-06T19:21:13.217Z",
"__v":0
}
问题
基于以上,我想问几个问题
near
和geoNear
与使用GeoJSON的2dsphere
索引时与nearSphere
非常相似,除了geoNear
提供额外数据和默认限制之外,这是正确的吗?也就是说,尽管具有不同的单位,但从概念上讲,这两个查询都将显示某个位置特定半径内的相关数据,尽管事实上该字段被称为radius
,用于nearSphere
和maxDistance
和near
skip
的性能损失,但仍然能够在查询和聚合中实现分页find()
函数允许一个可选参数来确定将返回哪些字段。聚合管道需要一个$project
阶段来执行相同的操作。在管道中使用$project
以优化速度/效率时,是否有特定的顺序,还是无关紧要我希望根据堆栈溢出规则允许这种类型的问题。谢谢。我用2dsphere索引尝试了下面的查询。我使用了聚合管道
对于下面的查询
db.items.createIndex({location:"2dsphere"})
在使用聚合管道时,它为您提供了更大的结果集灵活性。此外,聚合管道将提高运行地理相关搜索的性能
db.items.aggregate([
{
$geoNear: {
near: { type: "Point", coordinates: [ -110.8571443 , 35.4586858 ] },
key: "location",
distanceField: "dist.calculated",
minDistance: 2,
query: { "itemDescription": "A description" }
}])
关于您的$skip问题,下面的问题将让您对$skip操作有更多的了解
您可以根据需要使用$project。在我们的例子中,使用$project超过1000万的数据时,我们没有太多的性能问题我尝试了以下使用2dsphere索引的查询。我使用了聚合管道
对于下面的查询
db.items.createIndex({location:"2dsphere"})
在使用聚合管道时,它为您提供了更大的结果集灵活性。此外,聚合管道将提高运行地理相关搜索的性能
db.items.aggregate([
{
$geoNear: {
near: { type: "Point", coordinates: [ -110.8571443 , 35.4586858 ] },
key: "location",
distanceField: "dist.calculated",
minDistance: 2,
query: { "itemDescription": "A description" }
}])
关于您的$skip问题,下面的问题将让您对$skip操作有更多的了解
您可以根据需要使用$project。在我们的案例中,我们使用$project时没有太多性能问题超过1000万的数据请分享您收集的样本文档。聚合管道是一种数据流,因此数据通过管道进行过滤,因此它取决于您的要求。@SheshanGamage谢谢您的评论。请查看更新/编辑以查看示例文档的内容。请共享您收藏的示例文档。聚合管道是一种数据流,因此数据通过管道进行过滤,因此它取决于您的要求。@SheshanGamage谢谢您的评论。请参阅更新/编辑以查看示例文档的内容。谢谢。什么是
key
,根据您链接的答案,在limit
之前使用sort
是否更好?key是您的“位置”字段名:{“类型”:“点”,“坐标”:[-110.8571443,35.4586858]}是的,在管道末端使用limit总是很好的谢谢。什么是key
,根据您链接的答案,在limit
之前使用sort
是否更好?key是您的“位置”字段名:{“类型”:“点”,“坐标”:[-110.8571443,35.4586858]}是的,在管道末端使用限值总是好的