Để hợp lệ cho một "truy vấn không gian địa lý" "vị trí" phải ở kinh độ, vĩ độ đặt hàng và không được chứa bất kỳ tọa độ nào khác.
Các định dạng hợp lệ là
{
"location": [long,lat]
}
Hoặc
{
"location": { "lng": long, "lat": lat }
}
Hoặc GeoJSON
{
"location": {
"type": "Point",
"coordinates": [long,lat]
}
}
Một trường khác, chẳng hạn như "bán kính" là "trường khác" và không thể là một phần của cùng một mảng.
Tốt nhất là theo GeoJSON:
{
"location": {
"type": "Point",
"coordinates": [long,lat]
},
"radius": radius
}
Định nghĩa lược đồ mongoose có thể đơn giản như sau:
var geoSchema = new Schema({
"location": {
"type": String,
"coordinates": []
},
"radius": Number
});
Khi xử lý dữ liệu không gian địa lý tại tọa độ "quả địa cầu" thực, chỉ mục của bạn phải là "2dsphere" , mà bạn có thể tùy chọn xác định trên giản đồ là:
geoSchema.index({ "location": "2dsphere" })
Vì không có hỗ trợ thực tế nào cho đối tượng "Hình tròn" trong GeoJSON được hỗ trợ, nên bạn nên giữ một trường khác làm "bán kính" và lưu trữ "điểm trung tâm".
Lợi thế "lớn" của GeoJSON so với các định dạng "cặp tọa độ kế thừa" khác là khi trả về một thứ gì đó giống như "khoảng cách" từ một điểm qua geoNear
hoặc $geoNear
thì "khoảng cách" đó được xác định nhất quán bằng "mét". Đây cũng là cách bạn nên xác định bất kỳ giá trị "bán kính" nào trong bộ nhớ của mình để duy trì phù hợp với kết quả đó.
Với các định dạng lưu trữ khác, kết quả được trả về bằng "radian", mà bạn có thể muốn chuyển đổi và không muốn lưu trữ "bán kính" của hình tròn với đó làm phép đo.
Cách bạn giải quyết vấn đề này là xem xét dữ liệu trong biểu mẫu này:
{
"locationtype": "circle",
"location": {
"type": "Point",
"coordinates": [1,1]
},
"radius": 4
}
Sau đó, bạn sử dụng .aggregate()
với $geoNear
giai đoạn và một $redact
để lọc:
db.collection.aggregate([
// Find points or objects "near" and project the distance
{ "$geoNear": {
"near": {
"type": "Point",
"coordinates": [2,2]
},
"distanceField": "distance",
"query": { "locationType": "circle" }
}},
// Logically filter anything outside of the radius
{ "$redact": {
"$cond": {
"if": { "$gt": [ "$distance", "$radius" ] },
"then": "$$PRUNE",
"else": "$$KEEP"
}
}}
])
Bây giờ các giá trị được sử dụng trong ví dụ truy vấn chỉ là một ví dụ, nhưng như đã nêu với tọa độ kinh độ và vĩ độ "thực", các thuộc tính "khoảng cách" hoạt động như được thiết kế và nằm trong dung sai "mét" như đã đề cập trước đó.
Điểm mấu chốt ở đây là $geoNear
cả hai sẽ tìm thấy "gần" trung tâm "vòng tròn" bất kể loại đối tượng là gì. Không chỉ vậy, lệnh ở đây đang tạo ra một "phép chiếu" của một trường khác trong tài liệu ở đây như được đặt tên trong "distanceField". Điều này thể hiện khoảng cách từ "tâm" của vòng tròn tính bằng "mét".
Giai đoạn thứ hai ở đây sử dụng $redact
vì nó giống như một $project
và $match
giai đoạn đường ống trong một. Không giống như $match
toán tử này có thể đánh giá một điều kiện "logic" bằng cách so sánh các trường có trong tài liệu. Trong trường hợp này, các thao tác như $$PRUNE
loại bỏ tài liệu phù hợp với điều kiện "nếu" trong đó true
và "xóa" nó khỏi kết quả hoặc cách khác $$KEEP
tài liệu có điều kiện false
.
Tóm lại, nếu "khoảng cách" là "lớn hơn" thì "bán kính" của "đường tròn" thì đối tượng "nằm ngoài" của đường tròn và không "giao nhau". Nếu không thì "nó có".
Vì vậy, đó là kiến thức cơ bản của việc "xác định 'hình tròn' cho hình học trong bộ sưu tập và" sử dụng nó "để đạt được thứ gì đó giống như giao điểm giữa" Điểm "hoặc loại Đối tượng khác trong bán kính" hình tròn ".