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

MongoDB - Giao điểm không gian địa lý của hai đa giác

Vì vậy, nhìn vào điều này với một tâm trí tươi mới, câu trả lời đang nhìn chằm chằm vào mặt tôi. Điều quan trọng mà bạn đã nêu là bạn muốn tìm "điểm giao nhau" của hai truy vấn trong một phản hồi duy nhất.

Một cách khác để xem xét điều này là bạn muốn tất cả các điểm bị ràng buộc bởi truy vấn đầu tiên sau đó trở thành "đầu vào" cho truy vấn thứ hai, v.v. theo yêu cầu. Về cơ bản, đó là những gì một nút giao thông thực hiện, nhưng logic thực sự là theo nghĩa đen.

Vì vậy, chỉ cần sử dụng khung tổng hợp để xâu chuỗi các truy vấn phù hợp. Để có một ví dụ đơn giản, hãy xem xét các tài liệu sau:

{ "loc" : { "type" : "Point", "coordinates" : [ 4, 4 ] } }
{ "loc" : { "type" : "Point", "coordinates" : [ 8, 8 ] } }
{ "loc" : { "type" : "Point", "coordinates" : [ 12, 12 ] } }

Và đường dẫn tổng hợp theo chuỗi, chỉ cần hai truy vấn:

db.geotest.aggregate([
    { "$match": {
        "loc": {
            "$geoWithin": {
                "$box": [ [0,0], [10,10] ]
            }
        }
    }},
    { "$match": {
        "loc": {
            "$geoWithin": {
                "$box": [ [5,5], [20,20] ]
            }
        }
    }}
])

Vì vậy, nếu bạn xem xét điều đó một cách hợp lý, kết quả đầu tiên sẽ tìm thấy các điểm nằm trong giới hạn của hộp ban đầu hoặc hai mục đầu tiên. Các kết quả đó sau đó được truy vấn thứ hai xử lý và vì giới hạn hộp mới bắt đầu ở [5,5] loại trừ điểm đầu tiên. Điểm thứ ba đã bị loại trừ, nhưng nếu các giới hạn hộp được đảo ngược thì kết quả sẽ chỉ là tài liệu chính giữa.

Cách này hoạt động khá độc đáo đối với $geoWithin toán tử truy vấn so với các hàm địa lý khác:

Vì vậy, kết quả là cả tốt và xấu. Tốt ở chỗ bạn có thể thực hiện kiểu thao tác này mà không cần chỉ mục, nhưng không tốt vì một khi đường ống tổng hợp đã thay đổi kết quả thu thập sau thao tác truy vấn đầu tiên thì không thể sử dụng chỉ mục nào nữa. Vì vậy, bất kỳ lợi ích hiệu suất nào của một chỉ mục sẽ bị mất khi hợp nhất các kết quả "tập hợp" từ bất kỳ thứ gì sau Đa giác / Đa giác ban đầu như được hỗ trợ.

Vì lý do này, tôi vẫn khuyên bạn nên tính toán giới hạn giao nhau "bên ngoài" của truy vấn được cấp cho MongoDB. Mặc dù khung tổng hợp có thể thực hiện điều này do tính chất "chuỗi" của đường ống và mặc dù các giao điểm kết quả sẽ ngày càng nhỏ hơn, hiệu suất tốt nhất của bạn là một truy vấn duy nhất với các giới hạn chính xác có thể sử dụng tất cả các lợi ích của chỉ mục.

Có nhiều phương pháp khác nhau để thực hiện điều đó, nhưng để tham khảo, đây là cách triển khai bằng cách sử dụng JSTS thư viện, là một cổng JavaScript của JTS phổ biến thư viện cho Java. Có thể có những cổng khác hoặc các cổng ngôn ngữ khác, nhưng điều này có phân tích cú pháp GeoJSON đơn giản và được xây dựng trong các phương thức cho những thứ như lấy các giới hạn giao nhau:

var async = require('async');
    util = require('util'),
    jsts = require('jsts'),
    mongo = require('mongodb'),
    MongoClient = mongo.MongoClient;

var parser = new jsts.io.GeoJSONParser();

var polys= [
  {
    type: 'Polygon',
    coordinates: [[
      [ 0, 0 ], [ 0, 10 ], [ 10, 10 ], [ 10, 0 ], [ 0, 0 ]
    ]]
  },
  {
    type: 'Polygon',
    coordinates: [[
      [ 5, 5 ], [ 5, 20 ], [ 20, 20 ], [ 20, 5 ], [ 5, 5 ]
    ]]
  }
];

var points = [
  { type: 'Point', coordinates: [ 4, 4 ]  },
  { type: 'Point', coordinates: [ 8, 8 ]  },
  { type: 'Point', coordinates: [ 12, 12 ] }
];

MongoClient.connect('mongodb://localhost/test',function(err,db) {

  db.collection('geotest',function(err,geo) {

    if (err) throw err;

    async.series(
      [
        // Insert some data
        function(callback) {
          var bulk = geo.initializeOrderedBulkOp();
          bulk.find({}).remove();
          async.each(points,function(point,callback) {
            bulk.insert({ "loc": point });
            callback();
          },function(err) {
            bulk.execute(callback);
          });
        },

        // Run each version of the query
        function(callback) {
          async.parallel(
            [
              // Aggregation
              function(callback) {
                var pipeline = [];
                polys.forEach(function(poly) {
                  pipeline.push({
                    "$match": {
                      "loc": {
                        "$geoWithin": {
                          "$geometry": poly
                        }
                      }
                    }
                  });
                });

                geo.aggregate(pipeline,callback);
              },

              // Using external set resolution
              function(callback) {
                var geos = polys.map(function(poly) {
                  return parser.read( poly );
                });

                var bounds = geos[0];

                for ( var x=1; x<geos.length; x++ ) {
                  bounds = bounds.intersection( geos[x] );
                }

                var coords = parser.write( bounds );

                geo.find({
                  "loc": {
                    "$geoWithin": {
                      "$geometry": coords
                    }
                  }
                }).toArray(callback);
              }
            ],
            callback
          );
        }
      ],
      function(err,results) {
        if (err) throw err;
        console.log(
          util.inspect( results.slice(-1), false, 12, true ) );
        db.close();
      }
    );

  });

});

Sử dụng các biểu diễn "Đa giác" đầy đủ của GeoJSON ở đó vì điều này chuyển thành những gì JTS có thể hiểu và làm việc với. Rất có thể mọi thông tin đầu vào bạn có thể nhận được cho một ứng dụng thực tế cũng sẽ ở định dạng này thay vì áp dụng các tiện ích như $box .

Vì vậy, nó có thể được thực hiện với khung tổng hợp, hoặc thậm chí các truy vấn song song hợp nhất "tập hợp" kết quả. Nhưng trong khi khung tổng hợp có thể làm điều đó tốt hơn so với việc hợp nhất các bộ kết quả bên ngoài, kết quả tốt nhất sẽ luôn đến từ việc tính toán các giới hạn trước.



  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. MongoDB $ reverseArray

  2. Dự án lọc thuộc tính trong mảng lồng nhau thứ hai

  3. Tài liệu ngẫu nhiên từ MongoDB sử dụng dữ liệu mùa xuân

  4. Hàm tổng hợp MongoDB trong C #

  5. MongoDB $ Slice (phân trang mảng được nhúng)