簡體   English   中英

貓鼬MongoDB地理空間查詢

[英]Mongoose MongoDB GeoSpatial Query

我有一個Item集合,可以容納成千上萬的文檔。 在該集合上,我要執行地理空間查詢。 使用Mongoose,有兩個選項-find find()和Aggregation Pipeline。 我已經在下面顯示了兩者的實現:

貓鼬模型

首先,這是我的貓鼬模型的相關屬性:

// 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 match = {};
const sort = {};

// Query to make.
const query = {
    location: {
        $near: {
            $maxDistance: parseInt(req.query.maxDistance),
            $geometry: {
                type: 'Point',
                coordinates: [parseInt(req.query.lng), parseInt(req.query.lat)]
            }
        }
    },
    ...match
};

// Pagination and Sorting
const options = {
    limit: parseInt(req.query.limit),
    skip: parseInt(req.query.skip),
    sort
};

const items = await Item.find(query, undefined, options).lean().exec();

res.send(items);

聚集管道

假設需要計算距離:

// 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);

編輯-修改示例文檔

這是一個具有Item集合中所有屬性的文檔示例:

{
   "_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
}

問題

基於上述,我想問幾個問題。

  1. 我的普通貓鼬查詢的實現與聚合管道的使用之間是否存在性能差異?

  2. 它是正確的說, neargeoNear是非常相似nearSphere使用時2dsphere與GeoJSON的指標-除了geoNear提供額外的數據和默認限制? 也就是說,盡管這兩個查詢具有不同的單位,但從概念上講 ,這兩個查詢都將顯示某個位置特定半徑范圍內的相關數據,盡管事實上該字段稱為nearSpheremaxDistance radius ,具有near / geoNear

  3. 在上面的示例中,如何減少使用skip的性能損失,但仍然能夠在查詢和聚合中實現分頁?

  4. 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操作,聚合框架中的$ skip和$ limit有更多的了解

您可以根據需要使用$ project。 在我們的案例中,使用$ project超過1000萬數據沒有太多性能問題

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM