MongoDB查询附近
MongoDB query nearby
我有一个 Collection 用户、餐厅、产品
我想查询用户是否会在 his/her 应用程序中看到附近的餐厅(5 公里),它是 Open: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 公里的餐厅。
Collection 用户
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
Collection 餐厅
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
Collection 产品
id: 1
name: "Breakfast Whopper Jr."
price: ".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: ".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: ".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')
输出:
如果罗伯特在坐标 [ 22.222, 22.222 ] 中。
罗伯特将看到麦当劳和 Chick-fil-A 餐厅,因为 isOpen: true。
展示他们的产品,Big Mac 和 Spicy Chicken Sandwich,因为 isAvailable、isApproved: true 和 isArchived: false。
不是答案,只是一些想法,您应该评估一下自己。以下管道:
- 匹配
isApproved:true, isAvailable:true, isArchived:true
所以它假设并建议使用这个索引:
db.products.createIndex({
isAvailable: 1, isApproved: 1, isArchived: 1
})
- 一旦文档的数量被很好地缩小,查找应该不会花那么长时间。这里不需要索引,只要使用
foreignField:_id
,否则,我会在该字段上创建索引。
- $match
isOpen:true
会很慢,但如果可行的话,稍后会提高性能。 $lookup
中的 pipeline
可以帮助实现更好的性能,添加此索引(恕我直言)db.restaurants.createIndex({ _id: 1, isOpen: 1 })
- 我注释掉了我们在匹配中过滤掉的字段,因为我们知道值,并且可以设置,可能会提高性能(无法证明这一点)。
- 我们投影
location
因为我们需要那个字段
- 使用地理定位附近的东西,这几乎是正确的。这一步会比较慢,因为“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.
(同样值得记住的是,一些不是那么有用但活泼且终止良好的东西比非常复杂的滞后应用程序更好。同样,你会发现它是如何工作的,我根本不是专家。)
我有一个 Collection 用户、餐厅、产品 我想查询用户是否会在 his/her 应用程序中看到附近的餐厅(5 公里),它是 Open: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 公里的餐厅。
Collection 用户
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
Collection 餐厅
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
Collection 产品
id: 1
name: "Breakfast Whopper Jr."
price: ".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: ".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: ".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')
输出: 如果罗伯特在坐标 [ 22.222, 22.222 ] 中。 罗伯特将看到麦当劳和 Chick-fil-A 餐厅,因为 isOpen: true。 展示他们的产品,Big Mac 和 Spicy Chicken Sandwich,因为 isAvailable、isApproved: true 和 isArchived: false。
不是答案,只是一些想法,您应该评估一下自己。以下管道:
- 匹配
isApproved:true, isAvailable:true, isArchived:true
所以它假设并建议使用这个索引:
db.products.createIndex({
isAvailable: 1, isApproved: 1, isArchived: 1
})
- 一旦文档的数量被很好地缩小,查找应该不会花那么长时间。这里不需要索引,只要使用
foreignField:_id
,否则,我会在该字段上创建索引。 - $match
isOpen:true
会很慢,但如果可行的话,稍后会提高性能。$lookup
中的pipeline
可以帮助实现更好的性能,添加此索引(恕我直言)db.restaurants.createIndex({ _id: 1, isOpen: 1 })
- 我注释掉了我们在匹配中过滤掉的字段,因为我们知道值,并且可以设置,可能会提高性能(无法证明这一点)。
- 我们投影
location
因为我们需要那个字段 - 使用地理定位附近的东西,这几乎是正确的。这一步会比较慢,因为“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.
(同样值得记住的是,一些不是那么有用但活泼且终止良好的东西比非常复杂的滞后应用程序更好。同样,你会发现它是如何工作的,我根本不是专家。)