MongoDBé¢ç½ãã§ããã
ããã¥ã¡ã³ãã親åãªã®ã§ãããããã®ã§ããããªããªãæ¥æ¬èªã®è¨äºãç¡ãã£ããããã®ã§ãGeospatial Indexingã«ã¤ãã¦è©¦ãã¦ã¿ãäºãæ稿ãã¾ããï¼
ããã¥ã¢ã«ï¼MongoDB internal corp site
Geospatial Indexing 㯠MongoDB ver1.3.3以ä¸ã§ä½¿ãã¾ãã
å°ç空éã®ã¤ã³ããã¯ã¹ã¨ã¯
èªãã§åã®ãã¨ããªã®ã§ãããMongoDBã§ã¯äºæ¬¡å å°ç空éæ å ±ï¼å¤ãã®å ´åã緯度çµåº¦æ å ±ï¼ãã¤ã³ããã¯ã¹ã¨ãã¦æ¤ç´¢ãããããã¨ãåºæ¥ã¾ãã
æè¿ã®ã¬ã©ã±ã¼ãã¹ãã¼ããã©ã³ããã¯ç°¡åã«GPSæ©è½ãå©ç¨ãããã¨ãã§ãã¾ãããPCãã©ã¦ã¶ãªã©ã§ãä½ç½®æ å ±ãåå¾åºæ¥ãããã«ãªã£ãããhtml5ã®Geolocation APIï¼å³å¯ã«ã¯HTML5ã«å«ã¾ãã¦ã¯ããªãï¼ã®ç»å ´ãªã©ã§ãä»å¾ãã¾ãã¾ãä½ç½®æ å ±ã®å©ç¨é »åº¦ã¯é«ããªãããããªããã¨æãã¾ãã
ã§ããä½ç½®æ å ±ã£ã¦æ¤ç´¢ãé¢åã ã£ãããã¦ããã®ã¾ã¾ã§ä½¿ããããæ å ±ã§ã¯ãªãã§ãã
GeoHashãGeoHexãªã©ã¨ããã¨ãªã¢ï¼é¢ï¼æ å ±ã¨ãã¦æååã§ä¿åããæ¹æ³ãªã©ãããã¾ãããä¸é·ä¸çã
ä¾ãã°ãGeoHashã¯ãæåæ°ãé·ãã»ã©è©³ç´°ãªã¨ãªã¢ã表ããæ¤ç´¢ãªã©ãé常ã«ä½¿ãåæãããï¼æååæ¯è¼ã§æ¸ãï¼ã®ã§ããããã®ç¹å¾´ä¸ãè·é¢ã§ã®ã½ã¼ããé£ããã£ãããæ¤ç´¢ã¨ãªã¢ã®ç¯å²ãç´°ããæå®ãã¥ããã£ããã¨ããã¡ãªãããããã¾ãã
ã©ããªæè¡ããå¶ç´ã¨å©ä¾¿æ§ã®ãã¬ã¼ããªããªã®ã§ãä¸æã使ãåãã¦ããå¿ è¦ãããã¾ãã
ä»åã¯ãMongoDB ã® Geospatial Index ãç¨ãã¦ãè¿ãåºæ¤ç´¢ãã®ãããªãã®ãå®é¨ãã¦ã¿ã¾ãã
ãã¼ã¿ã®è¿½å
ä»åã¯ããã¹ãç¨ãªã®ã§æ¸è°·ä»è¿ã«ã©ã³ãã ãªãã¼ã¿ã100件ã»ã©è¿½å ãã¾ãã
以ä¸ã¯mongoã·ã§ã«ã§ã®æä½ã§ãã
// geotest ã¨ããDBã使ãã¾ã use geotest // æ¸è°·ä»è¿ã®çµåº¦ç·¯åº¦ var baseLng = 139.65534000898916; var baseLat = 35.63588652257869; var diffLng = 139.75730686689930 - baseLng; var diffLat = 35.67661462940957 - baseLat; // ã«ãã´ãªã®ãªã¹ã var categories = ['ã«ãã§', 'ãã¼', 'ã¬ã¹ãã©ã³']; // ã©ã³ãã ã«100件ã®ãã¼ã¿ã追å for (var i=1; i<=100; i++) { var myLng = baseLng + (Math.random() * diffLng); var myLat = baseLat + (Math.random() * diffLat); var myCategory = categories[ Math.floor(Math.random() * categories.length) ]; // ã©ã³ãã ãªãã¼ã¿ãä¿å db.places.save({ location: [myLng, myLat], // ä½ç½®æ å ± category: myCategory // ã«ãã´ãª }); }
shell 㧠JavaScript ãå©ç¨ã§ããã®ã¯å¹¸ãã§ããã
ã©ã³ãã ãã¼ã¿ã®çæã楽ã¡ãã§ãã
Index ãä½æ
次ã«ãå°ç空éã¤ã³ããã¯ã¹ãä½æãã¾ãã
MongoDB ã§ã¯è¤åã¤ã³ããã¯ã¹ãOKãªã®ã§ãä½ç½®æ å ±ã¨å ±ã«ãã«ãã´ãªæ å ±ã«ãã¤ã³ããã¯ã¹ãå¼µãã¾ãã
// ã¤ã³ããã¯ã¹ãä½æ db.places.ensureIndex({ location : "2d", // location ã« Geospatial Index ãå¼µã category : 1 // category ã« Index ãå¼µã });
æ¤ç´¢ãã¦ã¿ã
å®å ¨ä¸è´ã§æ¤ç´¢
db.places.find({ location : [139.66, 35.65] });
æ®éã®ã¤ã³ããã¯ã¹ã§æ¤ç´¢
db.places.find({ category : "ã¬ã¹ãã©ã³" });
$near ã§æ¤ç´¢
ããã ã¨ããã¾ãæå³ããªãã®ã§ããã$nearã使ãäºã§ãè¿ããã±ã¼ã·ã§ã³ãæ¤ç´¢ãããã¨ãã§ãã¾ãã
ï¼å®éã«ã¯è¿ãé ã«ä¸¦ã³æ¿ããããï¼
// [139.66, 35.65] ã®è¿ãã«ããåºã5件æ¤ç´¢ db.places.find({ location : { $near : [139.66, 35.65] } }).limit(5);
ãã¡ãããè¤åã¤ã³ããã¯ã¹ã§ã®æå®ãOKã§ãã
// [139.66, 35.65] ã®è¿ãã«ããã«ãã§ã5件æ¤ç´¢ db.places.find({ location : { $near : [139.66, 35.65] }, category : "ã«ãã§" }).limit(5);
$nearã®æ³¨æç¹
$near ã¯çµåº¦ã¨ç·¯åº¦ã®1度ãåãè·é¢ãæããã¨ãåæã¨ãã¦è¨ç®ãè¡ããã¾ãã
ä¾ãã°ã
ãåºç¹ã çµåº¦ï¼10° 緯度ï¼-84°
ããã
ãç¹Aã çµåº¦ï¼12° 緯度ï¼-84° ãç¹Bã çµåº¦ï¼10° 緯度ï¼-85°
ã¸ã®è·é¢ãè¨ç®ããå ´åãçµåº¦ã¨ç·¯åº¦ã®1度ãåãè·é¢ã§ããå¹³é¢ã¨ããã¨ãä¸å³ã®ãããªæãã«ãªããããç¹Bã®æ¹ãè¿ãããã«è¦ãã¾ãã
å®é¨ãã¦ã¿ã¾ãããã
// ç¹A ã®è¿½å db.places.save({ location: [12, -84], name: 'A' }); // ç¹B ã®è¿½å db.places.save({ location: [10, -85], name: 'B' }); // åºç¹ããè¿ããã¤ã³ãã®æ¤ç´¢ db.places.findOne({ location: { '$near': [10, -84] } });
çµæã¯ä¸è¨ã®ããã«ç¹Aãè¿ãã¾ãã
{ "_id" : ObjectId("4cef9fb0a22c7137b609561a"), "location" : [ 10, -85 ], "name" : "B" }
ã§ãããããã
å®éã«ã¯ãå°çã¯çä½ãªã®ã§å ´æã«ãã£ã¦1度ã¯å¤ããã¾ãã
ä»åã®çµåº¦ã»ç·¯åº¦ã®å ´åãä¸è¨ã®ãããªééã«ãªãã¨äºæ³åºæ¥ã¾ãã
â»å®éã®ç¸®å°ºã§ã¯ããã¾ããã
ä¸è¨ãµã¤ãã§ãå°çãçä½ã¨ãã¦äºç¹éã®è·é¢ãè¨ç®ãã¦ã¿ã¾ãããã
2地点間の距離と方位角 - 高精度計算サイト
ããã¨ã
ãåºç¹-ç¹Aéã®è·é¢ã23.270942 km ãåºç¹-ç¹Béã®è·é¢ã111.319491 km
ã¨ãªããå®éã«ã¯ç¹Aã®æ¹ãè¿ãäºããããã¾ãã
ãã®åé¡ã«è§£æ±ºãããããæ°ããçä½ã®ã¢ãã«ããã¼ã¸ã§ã³1.7.0ã§è¿½å ããã¾ããã
çä½ã¢ãã«ã使ç¨ãã¦æ±ãã
ãã®å ã®çä½ã¢ãã«ã¯ MongoDB ver1.7.0 以ä¸ã§ä½¿ãã¾ãã
å©ç¨ã¯ç°¡åã§ãã$near ã $nearSphere ã«å¤æ´ããã ãã§ãã
å®éã«ãã£ã¦ã¿ã¾ãããã
db.places.findOne({ location: { '$nearSphere': [10, -84] } });
çµæã¯ä¸è¨ã®ããã«æ£ããç¹Aãè¿ãããã«ãªãã¾ããã
{ "_id" : ObjectId("4cef9fada22c7137b6095619"), "location" : [ 12, -84 ], "name" : "A" }
ãªããçä½ã¢ãã«ã使ç¨ããå ´åã«ã¯ãä½ç½®æ å ±ã X(çµåº¦), Y(緯度) ã®é ã§ä½¿ã£ã¦ããã¨ä»®å®ãããããããã®é åºãå®ãå¿ è¦ãããã¾ãã
ãµã³ãã«ããã°ã©ã
ä»åã¯ãGoogleMaps APIã使ç¨ãã¦ãµã³ãã«ããã°ã©ã ãä½ã£ã¦ã¿ã¾ããã
mongodbã¨ã®ããåãã¯ä¸è¨ã®ãããªå½¢ã§PHPã«ã¦è¡ã£ã¦ãã¾ãã
<?php $geo = new getGeoInfo(); // è¦ã¤ããï¼ $geo->find(array( 'location' => array( '$nearSphere' => array( (float) $lng, (float) $lat, ), ), )); class getGeoInfo { private $mongo; private $collection; public function __construct() { // mongodb ã«æ¥ç¶ $this->mongo = new Mongo('mongodb://localhost:27077', array('persist' => 'myPersistId')); // collection ãé¸æ $this->collection = $this->mongo->selectDB('geotest201011')->selectCollection('places'); } public function find($query = array(), $limit = null) { // findãå®è¡ãã¦ãã«ã¼ã½ã«ãåå¾ $cursor = $this->collection->find($query); // JSONå½¢å¼ã§è¿ã echo '['; $isFirst = true; $i = 1; while ($cursor->hasNext()) { if (!is_null($limit) && $limit < $i) break; $item = $cursor->getNext(); $exportItem = array( 'location' => $item['location'], 'category' => $item['category'], ); echo ($isFirst) ? '' : ', '; echo json_encode($exportItem); if ($isFirst) { $isFirst = false; } ++$i; } echo ']'; } }
以ä¸ãé§ã足ã§ãããMongoDBã§ã®å°ç空éã¤ã³ããã¯ã¹ã®ãµã³ãã«ã§ããï¼