2016-10-24 60 views
0

我嘗試使用mongoDB作爲搜索引擎,並意識到這是一場災難。我試着做對5百萬個地理位置文件的簡單查詢。如何使用mongoDB作爲搜索引擎?

db.runCommand({ dropDatabase: 1 }) 

db.createCollection("places"); 

db.places.createIndex({ "locs.loc" : "2dsphere" }) 


function randInt(n) { return parseInt(Math.random()*n); } 
function randFloat(n) { return Math.random()*n; } 

for(var j=0; j<10; j++) { 
    print("Building op "+j); 
    var bulkop=db.places.initializeOrderedBulkOp() ; 
    for (var i = 0; i < 1000000; ++i) { 
    bulkop.insert( 
     { 
     locs: [ 
      { 
      loc : { 
       type: "Point", 
       coordinates: [ randFloat(180), randFloat(90) ] 
      } 
      }, 
      { 
      loc : { 
       type: "Point", 
       coordinates: [ randFloat(180), randFloat(90) ] 
      } 
      } 
     ] 
     } 
    ) 
    }; 
    print("Executing op "+j); 
    bulkop.execute(); 
} 

,然後我跑不匹配文檔的查詢:

db.runCommand(
    { 
    geoNear: "places", 
    near: { type: "Point", coordinates: [ 73.9667, 40.78 ] }, 
    spherical: true, 
    query: { category: "xyz" } 
    } 
) 

它需要4分鐘來回報您!

"waitedMS" : NumberLong(0), 
    "results" : [ ], 
    "stats" : { 
      "nscanned" : 10018218, 
      "objectsLoaded" : 15000000, 
      "maxDistance" : 0, 
      "time" : 219873 
    }, 
    "ok" : 1 

用於爲例somethink像獅身人面像指數於同查詢(其實根本就沒有索引的所有此類查詢使用,它只是滾動所有已經在內存中的reccord對其進行過濾)在200回ms

我做錯了什麼?他們的計算機上有32GB的免費內存,所有數據僅使用150MB。他們有什麼方法來加速mongoDB?或者明確地說我們不能使用mongoDB作爲搜索引擎?

+0

刪除「查詢」,在我的電腦上,我可以在1mln記錄上獲得6ms。 –

+0

{「nscanned」:117,「objectsLoaded」:59,「avgDistance」:0.001017138667266944,「maxDistance」:0.0016776194783600408,「time」:2} –

+0

Daniele,謝謝,但目的是爲了不刪除「查詢」:(因爲在運行查詢之前,您不知道它是否會匹配某些記錄......這裏的想法是模擬不返回(或非常少)記錄的查詢,並且4分鐘查看它們不相應記錄是不可接受的 – loki

回答

4

MongoDB的3.4rc與2mln記錄

我覺得你的代碼的問題是關係到「查詢」 PARAM,因爲你正在對集合另一個查詢沒有索引。

UPDATE(帶結果/數據):

db.runCommand({ dropDatabase: 1 }) 

db.createCollection("places"); 

db.places.createIndex({ "locs.loc.coordinates" : "2dsphere" }) 


function randInt(n) { return parseInt(Math.random()*n); } 
function randFloat(n) { return Math.random()*n; } 

for(var j=0; j<10; j++) { 
    print("Building op "+j); 
    var bulkop=db.places.initializeOrderedBulkOp() ; 
    for (var i = 0; i < 1000000; ++i) { 
    bulkop.insert( 
     { 
     locs: [ 
      { 
      loc : { 
       type: "Point", 
       coordinates: [ randFloat(180), randFloat(90) ] 
      } 
      }, 
      { 
      loc : { 
       coordinates: [ randFloat(180), randFloat(90) ] 
      } 
      } 
     ] 
     } 
    ) 
    }; 
    print("Executing op "+j); 
    bulkop.execute(); 
} 

Collection (i have more object, since i run the script more then once

這是查詢:

db.runCommand(
    { 
    geoNear: "places", 
    near: { type: "Point", coordinates: [ 73.9667, 40.78 ] }, 
    spherical: true 
    } 
) 

58ms: enter image description here

2ms的第二次運行: enter image description here

db.runCommand(
    { 
    geoNear: "places", 
    near: { type: "Point", coordinates: [ 73.9667, 40.78 ] }, 
    spherical: true, 
    query: { category: "private" } 
    } 
) 

156996ms: {locs.loc: enter image description here

創建 「類別」 索引之後。座標: 「2dsphere」,類別:1}

13562ms: enter image description here

UPDATE: 加入 「maxDistance」 可以執行396ms VS 6863ms

db.runCommand(
    { 
    geoNear: "places", 
    near: { type: "Point", coordinates: [ 73.9667, 40.78 ] }, 
    spherical: true, 
    query: {category: "private"}, 
    maxDistance: 1000000 
    } 
) 

maxDistance:1000000

"stats" : { 
    "nscanned" : NumberInt(107820), 
    "objectsLoaded" : NumberInt(1), 
    "avgDistance" : 938598.1782650856, 
    "maxDistance" : 938598.1782650856, 
    "time" : NumberInt(396) 
} 

沒有 「maxDistance」:

db.runCommand(
    { 
    geoNear: "places", 
    near: { type: "Point", coordinates: [ 73.9667, 40.78 ] }, 
    spherical: true, 
    query: {category: "private"} 
    } 
) 

"stats" : { 
    "nscanned" : NumberInt(2023916), 
    "objectsLoaded" : NumberInt(6), 
    "avgDistance" : 3013587.205365039, 
    "maxDistance" : 4263919.742779636, 
    "time" : NumberInt(6863) 
} 

來源: https://www.mongodb.com/blog/post/geospatial-performance-improvements-in-mongodb-3-2

更爲您的查詢使用,我認爲 「座標的陣列」 是無用的,因爲一個對象(一般)有1地理定位點。

另一種優化的方法是製作「geoWithin」,因爲沒有按「距離」進行排序(也許你想按「最投票餐廳」排序)。取決於場景。

+0

只是看到我以前的評論,目的是完全不刪除「查詢」:(因爲之前運行一個查詢,你不知道它是否會匹配一些記錄或不。 ..這裏的想法是模擬一個查詢返回沒有(或很少)的記錄和4分鐘,看到他們是不是相應的記錄是不可接受的 – loki

+0

你應該有一個索引然後 –

+0

但我不能dd索引在所有可能的查詢!在獅身人面像他們是沒有索引,它需要200毫秒返回 – loki