Warm tip: This article is reproduced from serverfault.com, please click

其他-附近的MongoDB查询

(其他 - MongoDB query nearby)

发布于 2020-12-03 01:29:54

我有一个要查询的集合用户,餐馆,产品,用户将在他/她的应用程序中看到附近的餐馆(5公里),其isOpen:true,并显示每个餐馆的产品isAvailable和isApproved = true和isArchived:false。

let kmToRadian = function(miles){
 var earthRadiusInMiles = 6378
 return miles / earthRadiusInMiles
}

var user = dbo.collection('users').findOne({_id: id})
var query = {
  "location": {
      $geoWithin: {
          $centerSphere: [ [22.222, 22.222], 5 / 6378.1] //sample coordinates
      }
  }
}


db.products.aggregate([
    { 
        $lookup: { 
            from: "restaurants", 
            localField: "restaurants", 
            foreignField: "_id", 
            as: "restaurant" 
        } 
    },
    {
        $match : {
            "restaurant.isOpen": true,
            "isApproved": true,
            "isAvailable": true,
            "isArchived": false
        }
    },
    {
        $project: {
            "restaurant.isOpen": 1,
            "isApproved": 1,
            "isAvailable": 1,
            "isArchived": 1,
            "name": 1
        } 
    }
])

在这里,我得到的产品是isAvailable,isApproved:true和isArchived false。现在,我想在附近找到5公里的餐厅。

收集用户

id: 1
name: "Robert"
location: Object
    type: "Point",
    coordinates: Array
     0: 11.111 //sample coordinates
     1: 11.111 //sample coordinates

id: 2
    name: "Jason"
    location: Object
        type: "Point",
        coordinates: Array
         0: 22.222 //sample coordinates
         1: 22.222 //sample coordinates

收藏餐厅

id: 1  
name: "Burger King"
location: Object
    type: "Point",
    coordinates: Array
       0: 11.111 //sample coordinates
       1: 11.111 //sample coordinates
isOpen: true

id: 2
name: "McDonald's"
location: Object
    type: "Point",
    coordinates: Array
       0: 22.222 //sample coordinates
       1: 22.222 //sample coordinates
isOpen: true

id: 3  
name: "Chick-fil-A"
location: Object
    type: "Point",
    coordinates: Array
       0: 22.333 //sample coordinates
       1: 22.333 //sample coordinates
isOpen: true

收集产品

id: 1
name: "Breakfast Whopper Jr."
price: "$1.29"
isAvailable: true
isApproved: true
createdAt: Tues Dec 01 2020 09:15:19 GMT+0800
updatedAt: Tues Dec 01 2020 09:15:19 GMT+0800
isArchived: false
shop: ObjectId('1')

id: 2
name: "Big Mac"
price: "$4.35"
isAvailable: true
isApproved: true
createdAt: Tues Dec 01 2020 09:15:19 GMT+0800
updatedAt: Tues Dec 01 2020 09:15:19 GMT+0800
isArchived: false
shop: ObjectId('2')

id: 3
name: "Spicy Chicken Sandwich"
price: "$3.29"
isAvailable: true
isApproved: true
createdAt: Tues Dec 01 2020 09:15:19 GMT+0800
updatedAt: Tues Dec 01 2020 09:15:19 GMT+0800
isArchived: false
restaurant: ObjectId('3')

输出:如果Robert在坐标[22.222,22.222]中。罗伯特将看到餐厅McDonald's和Chick-fil-A,因为isOpen:true。由于isAvailable,isApproved:true和isArchived:false,请显示其产品“巨无霸”和“辣鸡肉三明治”。

Questioner
Pinky Promise
Viewed
11
Minsky 2020-12-04 21:53:32

没有答案,只是一些想法,你应该评估自己。以下管道:

  1. 匹配isApproved:true, isAvailable:true, isArchived:true 因此,它假设并建议使用此索引:
db.products.createIndex({
  isAvailable: 1, isApproved: 1, isArchived: 1
})
  1. 一旦缩小文档数量,查找就不必花那么长时间了。在这里,只要foreignField:_id使用索引就不需要索引,否则,我将在该字段上创建索引。
  2. $ matchisOpen:true会很慢,但是如果可以的话,稍后会提高性能。pipeline$lookup能够帮助实现更好的性能,添加此指数(恕我直言)db.restaurants.createIndex({ _id: 1, isOpen: 1 })
  3. 我注释掉了我们在比赛中过滤掉的字段,因为我们知道该值并且可以设置,可能会提高性能(无法证明这一点)。
  4. 我们之所以location进入,是因为我们需要该领域
  5. 使用geo定位附近的位置,这几乎是正确的。这一步会很慢,因为“ geo”中没有索引,因此无法在此查询中创建索引。
db.products.aggregate([
  {
    $match: {
      "isApproved": true,
      "isAvailable": true,
      "isArchived": false
    }
  },
  {
    $lookup: {
      from: "restaurants",
      foreignField: "_id",
      localField: "restaurant",
      as: "restaurant"
    }
  },
  {
    $match: {
      "restaurant.isOpen": true
    }
  },
  {
    $project: {
      "restaurant.isOpen": 1,
      //"isApproved": 1,
      //"isAvailable": 1,
      //"isArchived": 1,
      "name": 1,
      "restaurant.location": 1
    }
  },
  {
    $match: {
      "restaurant.location": {
        $geoWithin: {
          $centerSphere: [
            [
              22.222,
              22.222
            ],
            5/6378.1] 
      }
  }
  }}
])

我必须说我不是专家,所以你需要测试和改进。另外,请仅包含JSON格式的文档,以便我们立即进行测试。我必须手动进行LIVE VERSION

(同样要记住,不是那么有用,但快速且完善的东西比一个非常复杂的应用程序最好。再次,你将了解它的工作原理,而且我也不是专家。)