æ¨æ¥ï¼2010/12/12ï¼éå¬ãããã第1å MongoDB JP ï¼ CouchDB JP åååå¼·ä¼ in Tokyoãã§ãMongoDBã®å°ç空éã¤ã³ããã¯ã¹ã®ç´¹ä»ãLTã¨ãã¦ããã¾ããã
åLTã§ç·å¼µãã¾ãã£ã¦ã¾ãããï¼ï¼ï¼çæ§ã®æããã¾ãªããã«æããããªãã¨ãç¡äºã«çµããã¾ããã
åå¼·ä¼å
¨ä½ã®å
容ã«ã¤ãã¦ã¯ã主å¬è
ã§ããã@doryokujinãããã¾ã¨ããããè¨äºãã覧ãã ããã
「第1回 MongoDB JP & CouchDB JP 合同勉強会 in Tokyo」を開催してきました! - doryokujin's blog
ã§ãå°ç空éã¤ã³ããã¯ã¹ã«é¢ããããã¤ãã®è£è¶³ã¨ãã³ããç¨ã®ããã¹ããæ¸ãã¦ããããã¨æãã¾ãã
Geospatial Indexingã®é度
æ¨æ¥ãGeospatial Indexingã®é度ã¯ã©ããªã®ãèãããæ°ä¸ä»¶ç¨åº¦ã®ã¬ã³ã¼ãã§ã¯ï¼æ®éã®Indexã«æ¯ã¹ã¦ï¼éãã¯æããªããã¨çããã®ã§ãããæ°ã«ãªã£ãã®ã§ã¡ãã¡ãã£ã¨æ¤è¨¼ãã¦ã¿ã¾ããã
ï¼ç°¡æçãªæ¤è¨¼ã§ãã®ã§åèç¨åº¦ã«ï¼
æ¤è¨¼ç°å¢
ï¼localhostä¸ã§ã®æ¤è¨¼ãåãã¹ãã¯3åè¨æ¸¬ãããã®å¹³åå¤ãæ²è¼ãã¦ãã¾ãï¼
ä¿å
1,000ä¸ä»¶ã®ã¬ã³ã¼ããã¤ã³ãµã¼ãããæã®çµæã§ãã
åå | æ®éã®Indexï¼ObjectIdï¼ | GeoIndex |
---|---|---|
åè¨æéï¼ç§ï¼ | 942.7 | 1,162.2 (+23%) |
ç§éã«å¦çããã件æ°ï¼/secï¼ | 10,613.4 | 8,606.7 (-19%) |
â»ã«ãã³å ã¯ãObjectIdã«æ¯ã¹ã¦ã®å¢æ¸ã®æ¯ç
GeoIndexã«ã¤ãã¦ã¯ããããããensureIndexãå®è¡ãã¦ããã¾ãã
ObjectIdã¨æ¯è¼ããã¨ãä¿åã§ã¯2å²ç¨åº¦ã®é度ä½ä¸ãè¦ããã¾ããã
ããã¯ãå
é¨çã«GeoHashåããããããã®è¨ç®å¦çãå¤ããå ãã¦ããã¨æããã¾ãã
æ¤ç´¢
ä¸è¨ã§ä¿åãããã¼ã¿ï¼1,000ä¸ä»¶ï¼ããObjectIdã§ã®æ¤ç´¢ã¨ãGeoIndexã®$near, $nearSphereã§æ¤ç´¢ããããã10ä¸åããæã®çµæã§ãã
ï¼findOne ã§å®è¡ï¼
åå | æ®éã®Indexï¼ObjectIdï¼ | $near | $nearSphere |
---|---|---|---|
åè¨æéï¼ç§ï¼ | 6.2 | 8.5 (+37%) | 9.3 (+50%) |
ç§éã«å¦çããã件æ°ï¼/secï¼ | 16,155.4 | 11,770.8 (-38%) | 10,770.8 (-51%) |
â»ã«ãã³å ã¯ãObjectIdã«æ¯ã¹ã¦ã®å¢æ¸ã®æ¯ç
æ¤ç´¢ã«é¢ãã¦ã¯ãObjectIdã¨æ¯è¼ãã4ã5å²ç¨åº¦ã®é度ä½ä¸ã¨ãªãã¾ããã
ããã¯ãåºç¹ã®GeoHashå¦çã«å ããGeoHashã§ã®åæ¹ä¸è´æ¤ç´¢ãè¡ã£ãå¾ã«ãè·é¢è¨ç®ã¨ã½ã¼ããè¡ããããããã¨æããã¾ãã
çµè«
ã¹ã©ã¤ã
ã¹ã©ã¤ãå 容ã®è£è¶³ã¨ãã³ããç¨ã³ã¼ããã¡
å°ç空éã®ã¤ã³ããã¯ã¹ãGeospatial Indexingã§ã¯ãäºæ¬¡å
ã®å°ç空éæ
å ±ããã¼ã«æ¤ç´¢ãè¡ããã¨ãåºæ¥ã¾ãã
çµåº¦ã»ç·¯åº¦ä»¥å¤ã®æ
å ±ãå
¥ãããã¨ãåºæ¥ã¾ãããæ®éã¯çµåº¦ã»ç·¯åº¦æ
å ±ã使ãã¨æãã¾ãã
Geospatial Index ã®ä½æ
Indexãä½ãã«ã¯ãæ®éã®Indexã¨åãã§ãã³ã¬ã¯ã·ã§ã³ã®ensureIndexã¡ã½ããã使ãã®ã§ãããGeospatial Index ã®å ´åã¯ã2dã¨ããæååãæå®ãã¾ãã
ãã ããã³ã¬ã¯ã·ã§ã³æ¯ã«ãä¸ã¤ã®Geospatial Indexããä½ãã¾ããã
db.shopinfo.ensureIndex({ // loc ãã£ã¼ã«ãã« Geospatial Index ãå¼µã loc : "2d" });
ãã¡ãããè¤åIndexã¨ãã¦æ®éã®Indexã¨åæã«æå®ããäºãåºæ¥ã¾ãã
db.shopinfo.ensureIndex({ loc : "2d", // Geospatial Index ãå¼µã category: 1 // ä»ã®ãã£ã¼ã«ãã« Indexãå¼µã });
ã¡ãªã¿ã«ãããã©ã«ãã§ã¯ã±180ã®floatå¤ãåãä»ãã¾ãããæ¡å¼µãå¯è½ã§ãã
db.shopinfo.ensureIndex({ loc : "2d", // Geospatial Index ãå¼µã }, { // ãªãã·ã§ã³ã§æ¡å¼µãã§ãã min: -1000, max: 1000 });
ä¿å
var lon = 139; var lat = 35; db.shopinfo.save({ name: 'å«è¶ããã', category: ['å«è¶åº'], loc: [lon, lat] // ä½ç½®æ å ± (x, y ã®é ããªã¹ã¹ã¡) // loc: [x: lon, y: lat] // é£æ³é åã§ã // loc: [lon: lon, lat: lat] // lon,latã§ã // loc: [foo: lon, bar:lat] // é©å½ãªååã§ãOK });
ã¯ã¨ãªã¼ï¼å®å ¨ä¸è´
// ã»ã¼ä½¿ãéãªãããã db.shopinfo.find({ loc: [139, 35] });
ã¯ã¨ãªã¼ï¼$near
db.shopinfo.find({ loc : { $near : [139.4, 35.4] // [139.4, 35.4]ããè¿ãé ã«ã½ã¼ã } });
ã¯ã¨ãªã¼ï¼$maxDistance
db.shopinfo.find({ loc : { $near : [139.4, 35.4], $maxDistance : 2 // æ大è·é¢ã ±2 ã®ãã®ãæ¤ç´¢ } });
ã¯ã¨ãªã¼ï¼è¤åæ¡ä»¶
db.shopinfo.find({ loc : { $near : [139.4, 35.4], $maxDistance : 2 }, category: 'å«è¶åº' });
ã¯ã¨ãªã¼ï¼geoNearã³ãã³ã
geoNearã³ãã³ãã使ãã¨ã詳細æ
å ±ãåå¾ãããã¨ãåºæ¥ã¾ãã
runCommandã¡ã½ããã§ãgeoNearã§ã³ã¬ã¯ã·ã§ã³åãæå®ãã¾ãã
æå®åºæ¥ããªãã·ã§ã³ã«ã¯ã"near", "maxDistance", "query"ãªãããããã¾ãã
db.runCommand({ geoNear: "shopinfo", near: [139.4, 35.4], maxDistance: 2, query: {category: 'å«è¶åº'} // æ®éã®ã¯ã¨ãªã使ãã });
ä¸è¨ãå®è¡ããã¨ä¸è¨ã®ããã«è¿ã£ã¦ãã¾ã
{ "ns" : "test.shopinfo", // âåºç¹ã«æå®ããæ å ±ãGeoHashåãããããå "near" : "1110100101001011000011000101000010111011111111011110", "results" : [{ "dis" : 0.5656861498877501, // è·é¢ï¼åä½ï¼åº¦ï¼ "obj" : { "_id" : ObjectId("4d01f5616919cb54afce6a77"), "name" : "å«è¶ããã", "category" : ["å«è¶åº"], "loc" : [139, 35] } }], "stats" : { "time" : 0, "btreelocs" : 0, "nscanned" : 1, "objectsLoaded" : 1, "avgDistance" : 0.5656861498877501, "maxDistance" : 0.5656861498877501 }, "ok" : 1 }
å°ç空éã¤ã³ããã¯ã¹ã§ã¯ãå é¨ã§GeoHashãä½µç¨ãããã¨ã§ãé«éæ§ãé«ãã¦ãã¾ãã
é åã®ã¯ã¨ãªã¼ï¼$within
é·æ¹å½¢ã®ã¢ãã«ã®å ´åãå³ä¸ã¨å·¦ä¸ï¼ãã¡ãããå³ä¸ã¨å·¦ä¸ã¨ãã§ãããã®ã ãã©â¦ï¼ã®ç¹æ å ±ãé åã§æå®ãã¾ãã
db.shopinfo.find({ loc : { $within : { $box : [[130, 30], [140, 35]] // (130, 30) - (140, 35)ã®é·æ¹å½¢å } } });
åå½¢ã®ã¢ãã«ã®å ´åãä¸å¿ç¹ã¨åå¾æ å ±ãé åã§æå®ãã¾ãã
db.shopinfo.find({ loc : { $within : { $center : [[135, 35], 4] // (135, 35)ããåå¾4ã®åã®ç¯å² } } });
å°çã¯çä½ï¼Sphere ã¯ã¨ãª
ï¼æ¬å½ã¯æ¥åã ãã¨ããããããããã³ãã¯ã¨ããããç½®ãã¦ããã¾ãï¼ï¼
çµåº¦1度ã®è·é¢ã¯èµ¤éããé¢ããã»ã©ãå°ãããªãã®ã§ã精度ãè½ã¡ã¦ãã¾ãã
ã¨ããããã½ã¼ãã®é çªãæ£ãããªãå ´åãããã使ãç©ã«ãªãã¾ããã
Ver.1.7.0以éã§ãµãã¼ããããSphereã¯ã¨ãªä½¿ãã¾ãããã
使ãæ¹ã¯ã$near ã®ä»£ããã« $nearSphere
db.shopinfo.find({ loc : { $nearSphere : [139.4, 35.4] } });
$center ã®ä»£ããã« $centerSphere
db.shopinfo.find({ loc : { $within : { // (135, 35)ããåå¾ 0.1ã©ã¸ã¢ã³ã®åã®ç¯å² $centerSphere : [[135, 35], 0.1] } } });
ã使ãã ãï¼ç°¡åï¼ï¼
ã¡ãªã¿ã«ã$boxSphereã¨ããã®ã¯ãä»çµã¿ä¸æå³ããªããªãã®ã§ç¡ããï¼
Sphereç³»ã®è·é¢åä½ï¼ã©ã¸ã¢ã³
Sphereç³»ã§ã¯ãè·é¢ã®åä½ãã©ã¸ã¢ã³ã«ãªãã¾ãã
å°çã§ã¯1ã©ã¸ã¢ã³ã6371kmã«ãªãã®ã§ããããåºã«è¨ç®ãè¡ãã°åé¡ãªãã¨æãã¾ãã
1ã©ã¸ã¢ã³ = (ç´) 6371 km
runCommandã§ã®çä½ã¢ãã«
runCommandã§ãçä½ã¢ãã«ã使ç¨ãããå ´åã¯ãspherical ãã©ã¡ã¼ã¿ã true ã«ãã¾ãã
db.runCommand({ geoNear: "shopinfo", near: [135, 35], query: {category: 'å«è¶åº'}, spherical: true // çä½ã¢ãã«ãæå¹ã« });
çµæã¯ãããªæãï¼æç²ï¼
"results" : [{ "dis" : 0.05718377899700883, // ã©ã¸ã¢ã³åä½ã§è¿ãã¾ã "obj" : { "loc" : [139, 35] } }],
æ¤ç´¢åºç¹ããæ¤ç´¢çµæã¾ã§ã®è·é¢ãdisã¨ããããããã£ã§è¿ã£ã¦ããï¼ã©ã¸ã¢ã³åä½ï¼ã®ã§ãä¸è¨ã®å ´åã0.057â¦ã©ã¸ã¢ã³Ã6371kmã§ã大ä½364 km ã«ãªããã
ã¨ããããã§ãä¸ç·ã«MongoDBã§éã³ï¼ï¼ï¼ã¾ãããï¼