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

Các truy vấn không gian địa lý có hoạt động trên mảng không? ($ geoWithin, $ geoIntersects)

Đây là một trong những câu hỏi có và không cần trả lời, vì có một mảng được hỗ trợ để kết quả đối sánh nhưng nó cũng có thể không phải là điều bạn thực sự muốn xem xét các hạn chế về cách đối sánh được thực hiện.

Thay đổi đáng chú ý mà bạn cần ở đây là bản thân các đối tượng không được xác định theo cách mà MongoDB sẽ nhận ra chúng như bạn hiện đã hình thành chúng. Có hai biểu mẫu tra cứu chỉ mục và tổng hợp là với các cặp tọa độ kế thừa (chỉ là một điểm x, y) hoặc dưới dạng GeoJSON với các đối tượng GeoJSON được hỗ trợ. Vấn đề của bạn là bạn có định dạng GeoJSON "psuedo" không thực sự phù hợp với thông số kỹ thuật và bạn đang cố gắng truy cập trực tiếp vào "tọa độ", nơi bạn cần một đối tượng cấp cao nhất như vậy:

{
    "regions": [
        {
            "name": "penta",
            "geometry": {
                "type": "Polygon",
                "coordinates": [[
                    [ 
                        -77.0322804898023610, 
                        -12.1271067552781560
                    ], 
                    [ 
                        -77.0336792618036270, 
                        -12.1255133434450870
                    ], 
                    [ 
                        -77.0326449349522590, 
                        -12.1239143495252150
                    ], 
                    [ 
                        -77.0300991833209990, 
                        -12.1238251884504540
                    ], 
                    [ 
                        -77.0299865305423740, 
                        -12.1262000752832540
                    ], 
                    [ 
                        -77.0322804898023610, 
                        -12.1271067552781560
                    ]
                ]]
            }
        },
        {
            "name": "triangle",
            "geometry": {
                "type": "Polygon",
                "coordinates": [[
                    [ 
                        -77.0313568040728570, 
                        -12.1266573492018090
                    ], 
                    [ 
                        -77.0325788855552670, 
                        -12.1246968022373030
                    ], 
                    [ 
                        -77.0300653204321860, 
                        -12.1246233756874440
                    ], 
                    [ 
                        -77.0313568040728570, 
                        -12.1266573492018090
                    ]
                ]]
            }
        }
    ]
}

Vì vậy, điều đó tóm tắt phần GeoJSON để vừa được hình thành tốt vừa được tách biệt khỏi các dữ liệu meta khác không phải là một phần của thông số kỹ thuật. Tốt nhất là bạn cũng nên lập chỉ mục, mặc dù không bắt buộc đối với $geoWithin hoặc $geoIntersects nó chắc chắn sẽ giúp:

db.regions.createIndex({ "regions.geometry": "2dsphere" })

Xác định đường dẫn đầy đủ đến định nghĩa GeoJSON trong phần tử mảng.

Sau đó, các truy vấn hoạt động bình thường:

db.regions.find({
    "regions.geometry" : { 
        "$geoIntersects" : { 
            "$geometry" : { 
                "type" : "Polygon" , 
                "coordinates" : [[
                    [ -77.02877718955278 , -12.123750122669545],
                    [ -77.03457042574883 , -12.123750122669545],
                    [ -77.03457042574883 , -12.12736341792724],
                    [ -77.02877718955278 , -12.12736341792724], 
                    [ -77.02877718955278 , -12.123750122669545]
                ]]
            }
        }
    }
})

Điều nào phù hợp với tài liệu trên. Nhưng tất nhiên có nhiều đối tượng trong mảng, vì vậy câu hỏi đặt ra là, đối tượng nào trong số này phù hợp? Không có câu trả lời nào được hỗ trợ, vì MongoDB đang khớp với "tài liệu" và không cho biết phần tử mảng nào được khớp theo bất kỳ cách nào.

Có một tùy chọn trong tập hợp $geoNear điều đó cho phép trả về đối tượng đã so khớp, trong trường hợp này, nó sẽ là "gần nhất". Và với chi tiết như vậy thì có thể sử dụng thông tin đó để so khớp phần tử mảng nào với dữ liệu meta đầy đủ chứa phần tử được tìm thấy cho "gần nhất" và trích xuất dữ liệu đó. Nhưng một lần nữa, nó chỉ là "gần" và cũng không bao giờ có thể trả về nhiều hơn một kết quả từ một mảng.

Nhưng nói chung, tốt hơn là chỉ trừ các đối tượng riêng biệt làm tài liệu trong bộ sưu tập của riêng chúng, nơi đối sánh với đối tượng riêng biệt chỉ là vấn đề khớp với tài liệu. Vì vậy, với mảng ở trên trong bộ sưu tập của riêng nó, bạn chỉ cần đưa ra truy vấn cho hình học phù hợp:

db.shapes.find({
    "geometry" : { 
        "$geoIntersects" : { 
            "$geometry" : { 
                "type" : "Polygon" , 
                "coordinates" : [ [ 
                    [ -77.02877718955278 , -12.123750122669545],
                    [ -77.03457042574883 , -12.123750122669545],
                    [ -77.03457042574883 , -12.12736341792724],
                    [ -77.02877718955278 , -12.12736341792724], 
                    [ -77.02877718955278 , -12.123750122669545]
                ]]
            }
        }
    }
})

Điều nào cung cấp cho (các) đối tượng chính xác như trong trường hợp này, hình dạng giao nhau giữa cả hai:

{
    "_id" : ObjectId("55f8d2fa66c2e7c750414b7a"),
    "name" : "penta",
    "geometry" : {
        "type" : "Polygon",
        "coordinates" : [[
            [
                    -77.03228048980236,
                    -12.127106755278156
            ],
            [
                    -77.03367926180363,
                    -12.125513343445087
            ],
            [
                    -77.03264493495226,
                    -12.123914349525215
            ],
            [
                    -77.030099183321,
                    -12.123825188450454
            ],
            [
                    -77.02998653054237,
                    -12.126200075283254
            ],
            [
                    -77.03228048980236,
                    -12.127106755278156
            ]
        ]]
    }
}
{
    "_id" : ObjectId("55f8d2fa66c2e7c750414b7b"),
    "name" : "triangle",
    "geometry" : {
        "type" : "Polygon",
        "coordinates" : [[
            [
                    -77.03135680407286,
                    -12.126657349201809
            ],
            [
                    -77.03257888555527,
                    -12.124696802237303
            ],
            [
                    -77.03006532043219,
                    -12.124623375687444
            ],
            [
                    -77.03135680407286,
                    -12.126657349201809
            ]
        ]]
    }
}

Vì vậy, bạn có thể sử dụng mảng nhưng bạn chỉ có thể thực sự khớp với tài liệu chứ không phải các thành viên mảng riêng lẻ là một phần của đối sánh, vì vậy điều này sẽ trả về tất nhiên các tài liệu về tổng thể và bạn sẽ cần tìm ra thành viên nào phù hợp với tiêu chí trong mã khách hàng .

Một lưu ý khác, một số nỗ lực truy vấn của bạn tìm cách "chia nhỏ" mảng tọa độ đối tượng thành các phần tử riêng lẻ. Điều này hoàn toàn không được hỗ trợ vì đối tượng chỉ có thể được xử lý tổng thể chứ không phải là các bộ phận của nó.




  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Xử lý BSON Marshaling tùy chỉnh

  2. Spring Data MongoDB và allowDiskUse

  3. tìm kiếm văn bản mongodb sử dụng nhiều ngôn ngữ

  4. Reactivemongo tuần tự hóa bản đồ thành BSONDocument

  5. kết nối với mongodb cục bộ từ bộ chứa docker