پیدا کردن نقاط جغرافیایی در یک محیط خاص

Find Geographical Locations in A Specific Environment

25 اردیبهشت 1401
درسنامه درس 64 از سری دوره جامع آموزش MongoDB
MongoDB: پیدا کردن نقاط جغرافیایی در یک محیط خاص (قسمت 66)

در جلسه قبل مسئله نزدیک بودن یک نقطه به نقاط مورد نظر خود را بررسی کردیم اما یکی دیگر از سوالات پرکاربرد در این زمینه بدین صورت است: ما محیط خاصی را در نظر داریم و می خواهیم بدانیم آیا نقطه x درون این محیط است یا خیر. این محیط می تواند یک مثلث، مستطیل یا هر شکل دیگری داشته باشد. برای انجام این کار باید ابتدا چند محل دیگر را به کالکشن places اضافه کنیم چرا که فعلا فقط یک سند را برایش داریم.

اولین محل انتخابی ما Conservatory of Flowers (گلخانه پارک Golden Gate) است که در نزدیکی آکادمی علوم کالیفرنیا قرار دارد:

https://www.google.com/maps/place/Conservatory+of+Flowers/@37.769887,-122.4640437,17z/data=!4m13!1m7!3m6!1s0x0:0x0!2zMzfCsDQ2JzE2LjAiTiAxMjLCsDI4JzE2LjAiVw!3b1!8m2!3d37.771104!4d-122.471114!3m4!1s0x808587459ac2a6e5:0x4cfc5cb588e07c1f!8m2!3d37.7722794!4d-122.4587899

ما می توانیم مختصات جغرافیایی را در همین URL پیدا کنیم:

@37.769887,-122.4640437

هشدار: مختصات به دست آمده بر اساس مرکز صفحه نمایش شما است بنابراین حتی اگر محلی را انتخاب کنید اما آن محل در گوشه صفحه شما باشد، باز هم مختصات نقطه ای به شما داده می شود که در وسط صفحه نمایش شما باشد. البته این موضوع برای ما مشکلی ایجاد نمی کند و مهم یادگیری فنون کار است نه به دست آوردن اعداد دقیق!

سپس به ترمینال رفته و این مکان جدید را در کالکشن خود ثبت می کنیم:

db.places.insertOne({name: "Conservatory of Flowers", location: {type: "Point", coordinates: [-122.4640437, 37.769887]}})

با این کار، مکان جدیدی را به کالکشن خود اضافه کرده ایم. محل بعدی مورد نظر ما Golden Gate Park Tennis Courts (زمین های تنیس پارک Golden gate) است:

https://www.google.com/maps/place/Golden+Gate+Park+Tennis+Courts,+San+Francisco,+CA+94117,+USA/@37.7701833,-122.4591205,20z/data=!4m5!3m4!1s0x8085809c1b40f217:0x11b7eab0fa42cee!8m2!3d37.7701879!4d-122.4589985

باز هم مختصات جغرافیایی را از آن خارج می کنیم:

@37.7701833,-122.4591205

سپس آن را به کالکشن خود اضافه می کنیم:

db.places.insertOne({name: "Golden Gate Park Tennis Courts", location: {type: "Point", coordinates: [-122.4591205, 37.7701833]}})

و در نهایت محل چهارمی را نیز باید اضافه کنیم که کاملا از پارک Golden Gate خارج باشد بنابراین از خیابان های اطراف یک محل را انتخاب کنید. من یک رستوران به نام Nopa را انتخاب می کنم:

https://www.google.com/maps/place/Nopa/@37.7748985,-122.4376937,20z/data=!4m5!3m4!1s0x808580afc823d4fd:0x58725c5c1643cf05!8m2!3d37.774901!4d-122.4375093

مختصات خارج شده از آن به شکل زیر هستند:

@37.7748985,-122.4376937

بنابراین می توانیم آن را نیز به عنوان آخرین محل به کالکشن خود اضافه کنیم:

db.places.insertOne({name: "Nopa", location: {type: "Point", coordinates: [-122.4376937, 37.7748985]}})

اگر می خواهید آن ها را ببینید، می توانید از یک دستور ساده find استفاده کنید. یادتان باشد که دقیق بودن نقاط انتخاب شده مهم نیست (چند متر جا به جایی تاثیری روی نتیجه ما ندارد).

حالا می خواهیم پارک Golden Gate را به عنوان یک محیط در نظر بگیریم تا ببینیم آیا اسناد درون کالکشن ما درون این محیط هستند یا نه. برای این کار چند روش وجود دارد که راحت ترین آن، رفتن به سربرگ Your Places در google maps و سپس تعریف کردن یک مستطیل دور پارک Golden Gate است:

همانطور که در ویدیوی بالا می بینید ما می توانیم به محل مورد نظر رفته و یک map جدید تعریف کنیم. در این map می توانیم marker های خود را اضافه کنیم که موقعیت دقیق یک نقطه را مشخص می کنند. ما به این داده ها نیاز داریم تا بتوانیم چهار نقطه مستطیل خود را تعریف کنیم بنابراین باید این کار را برای چهار گوشه پارک Golden Gate انجام بدهیم. من برای ساده تر شدن کار، نقطه های خودم را در اختیار شما می گذارم. برای راحت تر شدن کار و شلوغ نشدن کوئری ها، بهتر است این نقطه ها را در متغیر هایی درون ترمینال ذخیره کنیم:

const p1 = [-122.4547, 37.77473]

با اجرای این کد، مقدار p1 ذخیره می شود. حالا همین کار را برای سه نقطه دیگر نیز انجام می دهیم:

> const p1 = [-122.4547, 37.77473]
> const p2 = [-122.45303, 37.76641]
> const p3 = [-122.51026, 37.76411]
> const p4 = [-122.51088, 37.77131]

از آنجایی که shell بر اساس جاوا اسکریپت است، می تواند تمام این مقادیر را در خود نگه دارد تا هر زمان که بخواهیم از آن ها استفاده کنیم. حالا اگر بخواهیم یک کوئری بنویسیم که مشخص کند یک نقاط مورد نظر ما داخل یک محیط خاص هستند یا نه باید بگوییم (هنوز این کوئری کامل نیست بنابراین اجرا نکنید):

db.places.find({location: {$geoWithin: {$geometry: {type: "Polygon", coordinates: [[[]]]}}}})

اپراتور geoWithing$ به ما اجازه می دهد تمام نقاط درون یک شکل جغرافیایی را پیدا کنیم. ما باید به آن یک شیء پاس بدهیم که geometry$ را می گیرد. یادتان است که geometry$ همان GeoJSON بود بنابراین type و coordinate خواهد داشت. type را روی Polygon (به معنی «چند ضلعی») گذاشته ایم چرا که می خواهیم یک محیط را تعریف کنیم و این محیط چند ضلعی است. برای coordinates نیز مثل همیشه یک آرایه را داریم اما این بار کمی تفاوت دارد. درون این آرایه یک آرایه دیگر قرار می دهیم و سپس درون آن آرایه، مختصات نقاط خود را در قالب آرایه های مختلف قرار می دهیم. من این آرایه ها را درون متغیر های p1 تا p4 ذخیره کرده ام بنابراین به جای پاس دادن آرایه های خالی مانند کوئری بالا باید از این متغیر ها استفاده کنم:

db.places.find({location: {$geoWithin: {$geometry: {type: "Polygon", coordinates: [[p1, p2, p3, p4, p1]]}}}})

نکته: چند ضلعی ها (Polygon) باید همیشه با نقطه شروع، تمام شوند تا شکل کامل شود. به همین دلیل است که در کوئری بالا با p1 شروع کرده و دوباره آن را در آخر آورده ایم. با اجرای کوئری بالا، نتیجه زیر را می گیریم:

"_id" : ObjectId("5ec0bd1b7bc8c6a2b7e4ab85"),
 "name" : "California Academy of Sciences",   
 "location" : {                               
         "type" : "Point",                    
         "coordinates" : [                    
                 -122.468455,                 
                 37.7692285                   
         ]                                    
 }                                            
                                              
                                              
 "_id" : ObjectId("5ec0cbb27bc8c6a2b7e4ab86"),
 "name" : "Conservatory of Flowers",          
 "location" : {                               
         "type" : "Point",                    
         "coordinates" : [                    
                 -122.4640437,                
                 37.769887                    
         ]                                    
 }                                            
                                              
                                              
 "_id" : ObjectId("5ec0cdf57bc8c6a2b7e4ab87"),
 "name" : "Golden Gate Park Tennis Courts",   
 "location" : {                               
         "type" : "Point",                    
         "coordinates" : [                    
                 -122.4591205,                
                 37.7701833                   
         ]                                    
 }                                            

هر سه مکان به ما برگردانده شده اند چرا که داخل پارک Golden Gate بودند اما رستوران Nopa برگردانده نشده است چرا که داخل پارک Golden Gate نیست.

تمام فصل‌های سری ترتیبی که روکسو برای مطالعه‌ی دروس سری دوره جامع آموزش MongoDB توصیه می‌کند:
نویسنده شوید
دیدگاه‌های شما

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.

مقالات مرتبط
آخرین سوالات کاربران
5451218 در 4 سال قبل پرسیده:
ما را دنبال کنید
اینستاگرام روکسو تلگرام روکسو ایمیل و خبرنامه روکسو