sql >> Database teknologi >  >> NoSQL >> MongoDB

Fungerer geospatiale forespørgsler på arrays? ( $geoWithin, $geoIntersects )

Dette er et af de både ja- og nej-spørgsmål, der skal besvares, da ja, et array understøttes til at matche resultater i, men det er nok heller ikke det, du virkelig ønsker i betragtning af begrænsningerne for, hvordan matchningen udføres.

Den bemærkelsesværdige ændring, du har brug for her, er, at selve objekterne ikke er defineret på en måde, som MongoDB vil genkende dem, som du i øjeblikket har dem dannet. Der er to indeks- og generelle opslagsformer, der enten er med ældre koordinatpar (som kun er et x,y-punkt) eller som GeoJSON med understøttede GeoJSON-objekter. Dit problem er, at du har et "psuedo" GeoJSON-format, der ikke rigtig stemmer overens med specifikationerne, og at du forsøger at få direkte adgang til "koordinaterne", hvor du har brug for et objekt på øverste niveau som sådan:

{ "regions":[ { "name":"penta", "geometry":{ "type":"Polygon", "koordinater":[[ [ -77.0322804898023610, -12.1271067552781560 ], [ - 77.0336792618036270, -12.1255133434450870 ], [ -77.0326449349522590, -12.1239143495252150 ], [ -77.0300991833209990, -12.1238251884504540 ], [ -77.0299865305423740, -12.1262000752832540 ], [ -77.0322804898023610, -12.1271067552781560 ] ]] } }, { "navn":"trekant", "geometri":{ "type":"Polygon", "koordinater":[[ [ -77.0313568040728570, -12.1266573492018090 ], [ -77.032578288525], [ -77.032578288525], [ -32.03257828725,06.06.06,06,06.725,06.725,06,06,06,06,06. -12.1246233756874440 ], [ -77.0313568040728570, -12.1266573492018090 ] ]] } } ]}

Så det abstraherer GeoJSON-delen til at være både velformet og adskilt fra de andre metadata, der ikke er en del af specifikationen. Ideelt set ville du også indeksere, selvom det ikke er nødvendigt for $geoWithin eller $geoIntersects det hjælper bestemt:

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

Definerer den fulde sti til GeoJSON-definitionen i array-elementet.

Så fungerer forespørgsler korrekt:

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

Hvilket matcher dokumentet ovenfor. Men selvfølgelig er der flere objekter i arrayet, så spørgsmålet er, hvilken af ​​disse matchede? Som der ikke er noget understøttet svar på, da MongoDB matcher "dokumentet" og ikke på nogen måde angiver, hvilket array-element der blev matchet.

Der er en mulighed i sammenlægningen $geoNear der tillader det matchede objekt at blive returneret, hvor det i dette tilfælde ville være "nærmest". Og med sådanne detaljer er det så muligt at bruge den information til at matche hvilket array-element med fuld metadata, der indeholder det element, der blev fundet for "nærmeste", og udtrække disse data. Men igen er det kun "nær" og kan heller aldrig returnere mere end ét resultat fra et array.

Men generelt set er det bedre kun at udelukke de separate objekter som dokumenter i deres egen samling, hvor match til særskilt objekt blot er et spørgsmål om at matche dokumentet. Så med arrayet ovenfor i sin egen samling, udsteder du bare forespørgslen for den matchende geometri:

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

Hvilket giver det korrekte objekt(er), da formen i dette tilfælde skærer begge dele:

{ "_id" :ObjectId("55f8d2fa66c2e7c750414b7a"), "name" :"penta", "geometry" :{ "type" :"Polygon", "koordinater" :[[ [ -77.03228046, -8023 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" :"trekant", "geometri" :{ "type" :"Polygon", "koordinater" :[[ [ -77.03135680407286, -12.126657349201809], [-77.03257888555527, -12.124696802237303], [-77.03006532043219, -12.124623375687444], [ 

Så du kan bruge arrays, men du kan kun matche dokumentet og ikke de individuelle array-medlemmer, der var en del af matchet, så dette vil naturligvis returnere dokumenter som helhed, og du skal regne ud, hvilke medlemmer der matchede kriterierne i klientkoden .

På en anden note søger flere af dine forespørgselsforsøg at "dele" objektkoordinatarrayet i individuelle elementer. Dette understøttes slet ikke, da objektet kun kan behandles som en helhed og ikke som dets "Point"-dele.




  1. Mongoose-forespørgsel efter dato

  2. Brug af wait.for med nodejs og mongoskin for at undgå tilbagekaldshelvede

  3. TypeError:Object.keys kaldet på ikke-objekt ved opdatering af dokument

  4. Jeg får en fejl under implementering af Node.Js app med mongoDB på Elastic Beanstalk