エロサイトの作り方

2013年11月から勉強しながらエロサイトを作っています。

MongoDBでgeo field only has 1 element

MongoDBではランダムソートをかけることができなくて、地理空間Indexを設定したフィールドから抽出することでランダムっぽくさせる、ということをやるわけですが。

ランダムで取り出す例

データを入れる

mongo> for(i=0; i<1000; i++) {
mongo>   db.sandbox.insert({num:i, random:[Math.random(), Math.random()]});
mongo> }

地理空間Indexを作る

mongo> db.sandbox.ensureIndex({random:'2d'});

取り出す

mongo> db.sandbox.find({random: {$near: [Math.random(), Math.random()]}},{_id:0, num:1}).limit(10);
{ "num" : 867 }
{ "num" : 839 }
{ "num" : 631 }
{ "num" : 678 }
{ "num" : 559 }
{ "num" : 229 }
{ "num" : 395 }
{ "num" : 344 }
{ "num" : 60 }
{ "num" : 690 }

もう一回やると違う値を取って来れる

mongo> db.sandbox.find({random: {$near: [Math.random(), Math.random()]}},{_id:0, num:1}).limit(10);
{ "num" : 159 }
{ "num" : 962 }
{ "num" : 625 }
{ "num" : 803 }
{ "num" : 63 }
{ "num" : 403 }
{ "num" : 975 }
{ "num" : 287 }
{ "num" : 953 }
{ "num" : 932 }

ここまでは良い。

地理空間Indexを使うと$existsの挙動がおかしくなる

$exists:0が使えない

mongo> db.sandbox.count({random:{$exists:0}})
Mon Jul 28 18:54:35.436 count failed: {
  "errmsg" : "exception: geo field only has 1 element :: caused by :: $exists: 0.0",
  "code" : 13068,
  "ok" : 0
} at src/mongo/shell/query.js:180

なぜかエラー。

一方、$exists:1は使える

mongo> db.sandbox.count({random:{$exists:1}})
1000

そして$notを付けても使える

mongo> db.sandbox.count({$not:{random:{$exists:1}}})
0

ほげぇ……

結論としては、バグでした

素直に最新の2.6系を使えればいいんだけど、Elasticsearchの件でバージョンアップできないので辛い。