MongoDB
 sql >> Cơ Sở Dữ Liệu >  >> NoSQL >> MongoDB

Lọc tài liệu theo khoảng cách được lưu trữ trong tài liệu với $ gần

Giả sử bạn đã tìm cách xử lý dữ liệu sự kiện khi bạn nhận được và có nó trong tay (nếu bạn chưa có, thì đó là một câu hỏi khác, nhưng hãy xem con trỏ khả dụng ), thì bạn nên có một đối tượng với dữ liệu đó để truy vấn người dùng.

Do đó, đây không phải là trường hợp đánh giá JavaScript với $where , vì nó không thể truy cập dữ liệu truy vấn được trả về từ $near vẫn hoạt động. Thay vào đó, những gì bạn muốn là $geoNear từ khung tổng hợp. Điều này có thể chiếu "khoảng cách" được tìm thấy từ truy vấn và cho phép giai đoạn sau "lọc" kết quả dựa trên giá trị được lưu trữ của người dùng cho khoảng cách tối đa mà họ muốn di chuyển đến các sự kiện đã xuất bản:

// Represent retrieved event data
var eventData = {
  eventLocation: {
    latlong: [long,lat]
  }
};

// Find users near that event within their stored distance
User.aggregate(
  [
    { "$geoNear": {
      "near": {
        "type": "Point",
        "coordinates": eventData.eventLocation.latlong
      },
      "distanceField": "eventDistance",
      "limit": 100000,
      "spherical": true
    }},
    { "$redact": {
      "$cond": {
        "if": { "$lt": [ "$eventDistance", "$maxDistance" ] },
        "then": "$$KEEP",
        "else": "$$PRUNE"
      }
    }}
  ]
  function(err,results) {
    // Work with results in here
  }
)

Bây giờ bạn cần phải cẩn thận với số được trả về, vì dường như bạn đang lưu trữ trong "cặp tọa độ kế thừa" thay vì GeoJSON, nên khoảng cách trả về từ thao tác này sẽ tính bằng radian và không phải là khoảng cách chuẩn. Vì vậy, giả sử bạn đang lưu trữ theo "dặm" hoặc "km" trên các đối tượng người dùng thì bạn cần tính toán thông qua công thức được đề cập trong hướng dẫn dưới " Tính khoảng cách bằng hình học hình cầu " như đã đề cập trong sách hướng dẫn.

Điều cơ bản là bạn cần chia cho bán kính xích đạo của trái đất, là 3.963,2 dặm hoặc 6.378,1 km để chuyển đổi so với những gì bạn đã lưu trữ.

Thay vào đó là lưu trữ trong GeoJSON, nơi có số đo nhất quán tính bằng mét.

Giả sử "kilômét" thì dòng "nếu" trở thành:

"if": { "$lt": [
    "$eventDistance",
    { "$divide": [ "$maxDistance", 6,378.1 ] }
 ]},

Để so sánh một cách đáng tin cậy giá trị ki lô mét đã lưu trữ của bạn với kết quả radian được kiểm tra lại.

Một điều khác cần lưu ý là $geoNear có "giới hạn" mặc định là 100 kết quả, vì vậy bạn cần "bơm" đối số "giới hạn" ở đó lên con số để người dùng dự kiến ​​có thể khớp. Bạn thậm chí có thể muốn làm điều này trong "danh sách phạm vi" của id người dùng cho một hệ thống thực sự lớn, nhưng bạn có thể mở rộng đến mức bộ nhớ cho phép trong một hoạt động tổng hợp duy nhất và có thể thêm allowDiskUse khi cần thiết.

Nếu bạn không điều chỉnh tham số đó, thì chỉ 100 kết quả gần nhất (mặc định) sẽ được trả về, thậm chí có thể không phù hợp với thao tác lọc tiếp theo của bạn là lọc những kết quả "gần" sự kiện bắt đầu. Mặc dù vậy, hãy sử dụng cách hiểu thông thường, vì bạn chắc chắn có khoảng cách tối đa để lọc ra cả những người dùng tiềm năng và điều đó cũng có thể được thêm vào truy vấn.

Như đã nêu, điểm ở đây là trả về khoảng cách để so sánh, do đó, giai đoạn tiếp theo là $redact hoạt động có thể khớp giá trị "khoảng cách di chuyển" của chính người dùng với khoảng cách trả về từ sự kiện. Kết quả cuối cùng chỉ cung cấp cho những người dùng nằm trong khoảng cách xa với sự kiện của họ, những người sẽ đủ điều kiện nhận thông báo.

Đó là logic. Bạn chiếu khoảng cách từ người dùng đến sự kiện và sau đó so sánh với giá trị được lưu trữ của người dùng về khoảng cách mà họ chuẩn bị di chuyển. Không có JavaScript và tất cả các toán tử gốc làm cho nó khá nhanh.

Cũng như đã lưu ý trong các tùy chọn và bình luận chung, tôi thực sự khuyên bạn nên sử dụng chỉ mục "2dsphere" để tính toán khoảng cách hình cầu chính xác cũng như chuyển đổi sang lưu trữ GeoJSON để lưu trữ tọa độ trong cơ sở dữ liệu của bạn Đối tượng, vì chúng đều là tiêu chuẩn chung tạo ra kết quả nhất quán.



  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Đăng ký không hoạt động - Máy chủ trả về Mã lỗi 404

  2. Tôi nên cấu trúc các lệnh gọi Reativemongo lồng nhau trong ứng dụng play2 của mình như thế nào?

  3. chỉ thực hiện một trong nhiều công việc trùng lặp với sidekiq?

  4. có cách nào để tự động tạo ObjectId khi Mô hình mongoose mới không?

  5. MongoError:cấu trúc liên kết đã bị phá hủy sailsjs