2014-08-30 81 views
0

我工作蒙戈和我想要做以下的事情:指數UPSERT一個蒙戈子文檔

when a set of (lat, lon, uid) comes in: 

1. the collection has lat as unique index, also for each lat the lon index is unique 
2. if (lat, lon) pair exists in this collection, update uid in the sub-document 
3. if (lat) exists in this document , insert (lon, uid) in the lons sub-document 
4. if (lat) document doesn't exist, create lat document and do 2 

[{ 
    "lat" : 1, (doc is unique by lat) 
    "lons" : [ 
     { 
      "lon" : 2, (the subdocument is unique by lon) 
      "uid" : 3 
     }, 
     { 
      "lon" : 3, 
      "uid" : 3 
     } 
    ] 
}, 
{ 
    "lat" : 2, 
    "lons" : [ 
     { 
      "lon" : 2, 
      "uid" : 4 
     } 
    ] 
}] 

我試着做下面的事情,但顯然它不工作作爲我的想象。

db.zones.update({'lat': 90}, {$push: {lons: {'uid' : 0, 'lon': -18}}}, { upsert: true }) 
db.zones.ensureIndex({'lat': -1, 'lons.lon':1}, {unique: true}) 

我檢查了這個帖子Can mongo upsert array data?和其他人,但不知何故,他們都沒有工作。我不知道這是我的問題還是mongo問題。謝謝!

回答

2

我建議你重新考慮你的架構:

  • upsert應用在文件級,不與你的方案是如何組織很好地適應。如果在lons數組中找不到匹配項,則要將其推送到現有文檔而不是創建新文檔。

  • 文件,包括與無限的發展會導致頻繁的文件移動和性能問題陣列(參見:Why shouldn't I embed large arrays in my documents?

  • 你的架構本身不借給地理空間索引(這可能需要經度/緯度對作爲一個數組或嵌入式文檔)。我猜這對你的用例來說並不重要,因爲你確保了一個正常的唯一索引,但它可能是值得考慮的。

一個更好的架構(假設你不打算使用地理空間查詢)將是:

{ 
    lon: -74.0059, 
    lat: 40.7127, 
    uid: 3 
} 

有了這個修訂方案,您的更新要求更爲簡單。

  1. 集合已緯度作爲唯一指標,也是每個緯度的經度指數是唯一

你仍然要確保唯一索引:

 db.zones.ensureIndex({'lat': 1, 'lon':1}, {unique: true}) 

2.如果此集合中存在(lat,lon)對,則更新子文檔中的uid

3.如果(lat)存在於本文檔中,請在lons子文檔中插入(lon,uid)

4。如果(LAT)文件不存在,創建LAT文件,做2

所有這個邏輯現在可以通過一個upsert處理:

db.zones.update(

    // query criteria 
    { lat: 40.7127, lon: -74.0060 }, 

    // update 
    { $set: { 
     uid: 3 
    }}, 

    // options 
    { 
     upsert: true 
    } 
) 

如果你想保留uid更新的時現有的文檔,你也可以使用$setOnInsert運營商(而不是$set):

db.zones.update(

    // query criteria 
    { lat: 40.7127, lon: -74.0060 }, 

    // update 
    { $setOnInsert: { 
     uid: 3 
    }}, 

    // options 
    { 
     upsert: true 
    } 
) 
+0

我之前想這個。問題在於,我將有大約10k點lon和10k lat,這意味着我將有這樣創建的1億文件。這仍然是一個很好的設計? – 2014-08-30 12:49:14

+0

絕對!閱讀我在[大型嵌入式數組]上引用的博文(http://askasya.com/post/largeembeddedarrays)。在這兩種情況下,對於唯一的經度/長度對,您都有相同數量的索引條目,因此請將索引視爲大小相同。但是,如果在每個'lat'文檔中嵌入10k lon值的數組,則隨着文檔超出磁盤空間(每次文檔移動時,該文檔的所有索引條目也必須是更新),如果你需要檢索文檔中的一個點,服務器必須將整個文檔加載到RAM中。 – Stennie 2014-08-30 13:08:32

+0

我明白了。對於以這種方式創建的NxN文檔是查詢時間O(1)還是O(N^2)?你也可以推薦我一些更多的資源查詢,udpate mongo費用?大O的東西?非常感謝你 !! – 2014-08-30 13:53:54