附近的MongoDB查询

附近的MongoDB查询,mongodb,mongodb-query,geolocation,aggregation-framework,Mongodb,Mongodb Query,Geolocation,Aggregation Framework,我收集了用户、餐厅、产品 我想查询该用户将在其应用程序中看到附近的餐馆(5公里),isOpen:true,并显示每个餐馆的产品,isAvailable and isApproved=true and isArchived:false let kmToRadian = function(miles){ var earthRadiusInMiles = 6378 return miles / earthRadiusInMiles } var user = dbo.collection('use

我收集了用户、餐厅、产品 我想查询该用户将在其应用程序中看到附近的餐馆(5公里),isOpen:true,并显示每个餐馆的产品,isAvailable and isApproved=true and 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
        } 
    }
])
在这里,我得到的产品是可提供的,是经批准的:正确和错误。现在,我想去附近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]中。 罗伯特将参观麦当劳和奇克菲拉餐厅,因为伊索彭:是的。
展示他们的产品是巨无霸和辣味鸡肉三明治,因为它是可用的,被批准的:正确的,被归档的:错误的。

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

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
        } 
    }
])
  • 匹配
    isApproved:true、isAvailable:true、isArchived:true
    因此,它假设并建议使用此索引:
  • 一旦文档的数量被很好地缩小,查找就不会花那么长时间。这里不需要索引,只要使用
    foreignField:\u id
    ,否则,我将在该字段上创建索引
  • $match
    isOpen:true
    会很慢,但如果这样做有效的话,以后会提高性能<
    $lookup
    中的code>pipeline可以帮助实现更好的性能,添加这个索引(IMHO)
    db.restaurants.createIndex({u id:1,isOpen:1})
  • 我注释掉了我们在match中过滤掉的字段,因为我们知道值,并且可以设置,这可能会提高性能(无法证明这一点)
  • 我们在中投影
    位置
    ,因为我们需要该字段
  • 使用地理定位来定位附近的东西,这几乎是正确的。这一步将相当缓慢,因为“geo”中没有索引,并且无法在此查询中创建索引
  • 我必须说我不是专家,所以这取决于你的测试和改进。另外,请只包括JSON格式的文档,这样我们就可以马上测试了。我必须手动完成这项工作


    (同样值得记住的是,有些东西不是很有用,但是很快就结束了,比一个非常复杂的laggy应用程序更好。同样,你会发现它是如何工作的,我一点也不是专家。)

    @Minsky Hi,我能对这类查询使用什么提出建议吗。
    db.products.aggregate([{$lookup:{from:'restaurants',localField:'restaurants',foreignField:'u id',as:'shop'},},{$match:{'restaurant.isOpen':true}}])
    下一步我想得到的是餐厅的产品,可用且已批准的产品是真的,而isArchived是假的。我做得对吗?@MinskyHi,@Minsky很抱歉迟迟没有回复。它没有返回靠近loaction的餐厅。它返回我一个空数组。太好了,不客气
    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] 
          }
      }
      }}
    ])