MongoDB實現mysql主鍵autoincrement

來源:互聯網
上載者:User

MongoDB建立表預設有一個_id欄位來作為autoincrement自增實現,而這個_id欄位類型是objectid類型(objectid 是12位元組的BSON類型)。ObjectId的詳細解釋。

而現在因為資料庫遷移,將項目中原mysql的一些locations表移植到mongodb上面。對於locations 使用mongodb 2d loc 索引能夠更快的進行資料檢索,同時避免原mysql需要經過複雜的經緯度查詢。

那麼資料移轉後主要的要求有

1、資料庫表的遷移不會影響表與表之間的關係,繼續保持表之間的主外鍵關係。

2、lat 與 lng 欄位在mongodb 新表中合并為一個欄位loc,同時對loc加以2d索引。

對於第二點主要影響是在代碼之中,可以看看這裡。就不做詳細描述了。

那麼現在主要要做的事情就是,維持表與表的關係與主外鍵關係。我們以event 與 對應的 event_locations為例

event中有一個外鍵location_id,location_id就是event_locations的主鍵id;而現在mongodb中建立event_locations表,同時要保持event_locations與event的主外鍵參考關聯性。

因為mongodb表中預設有著_id這樣一個主鍵,那現在我們的資料移轉以及mongodb event_locations表結構構建有兩種選擇

1、event_locations 主鍵以_id,即將原mysql event_locations 的id 替換為 _id。也就是如下表結構

查看原始碼列印協助
1 { "_id" : ObjectId("51243bdb383ca83413000000"),  "topic_id" : 103874, "name" : "xixi aaahah", "address" : "xxxbbbb cccccc", "loc" : [ 30.11, 112.02 ], "created" : 1361329114, "updated" : 0 }
優缺點分析

優點就是 使用預設的_id主索引值,速度快檢索方便。_id自增不必維護,有mongodb自行完成。

缺點很明顯 event中的location_id外鍵,原來類型是int,現在改用_id objectid類型作為主鍵id,location_id類型必須要更改為char(32)了。且程式碼還需要一定的更改。

最大的缺點就是目前項目已經上線,直接更改資料庫表可能會帶來不可預知的問題;對於運營維護可能帶來很大壓力。且對於目前event已有的location_id資料需要進行同步更新。

2、保持原來的event_locations表結構,使用id繼續維持與event location_id的主外鍵關係。

 代碼如下 複製代碼

 { "_id" : ObjectId("51243bdb383ca83413000000"), "id" : 2354, "topic_id" : 103874, "name" : "xixi aaahah", "address" : "xxxbbbb cccccc", "loc" : [ 30.11, 112.02 ], "created" : 1361329114, "updated" : 0 }

優缺點分析

優點 不必去更改event location_id的資料類型,且location_id的資料不必修改;只用將event_locations資料完整匯入到新表中即可。

缺點 要維持id的自增屬性,而mongodb預設是_id才有自增屬性的,所以我們要用某種方法實現id的自增實現。_id會佔用儲存空間(預設的_id原本可以刪除的,但考慮到以後可能會用到就儲存了)。

我現在採用的是第2種方式,主要原因如下

1、項目已上線,且已經有了使用者資料;對於直接更改資料表與操作資料會帶來很大的風險。強烈不推薦。

2、event_locations資料幾乎不用同步,只需要單嚮導入到mongodb 新表就好。

3、程式碼變動最小,目前程式碼更改就是新的loc(lng+lat)儲存與id的自增實現。而第一種除了這些,還需要把所有的id替換為_id,資料類型也要從int變為string。

在確定瞭解決方法之後那麼現在主要的難題就是怎麼實現id的自增?

目前也有兩種方法

1、傳統實現,每次在event_locations insert之前,全表id desc排序得到最大的id值,對id值+1既得到了最新的id值從而實現了自增。

2、使用mongodb的findAndModify()方法實現,獨立一個ids表用來記錄所有可能需要id自增的值。

同樣簡要說明下這兩種實現id自增的方法優劣。

第一種方法

優點 不用構建ids表(工具表),免於維護

缺點 每次都要進行全表索引排序且尋找到最大id那條記錄,在進行+1

第二種

優點 findandmodify() 原子操作(瞭解原子操作請查看這裡),尋找並修改,直接返回當前操作的這個文檔內容。

缺點 要構建維護ids表,即項目中所有表可能需要自增的表都有一條記錄存在於其中。

無論採用哪種方法都要修改程式碼,即id autoincrement部分需要程式實現。我採用的是第二種方法。

主要考慮還是效能問題,避免每次insert之前都要對event_locations進行全部的索引排序。而維護ids這樣的表會很簡單且效能上忽略不計,詳細表結構如下

 代碼如下 複製代碼


{ "_id" : ObjectId("5147ca1a08c2c1bc12abdb4c"), "id" : 2356, "tablename" : "topic" }

// _id 預設主鍵,mongodb自增

// id  表中自增主索引值

// tablename 表名

擷取下一個id的核心代碼,繼承了mongodb的ids Model。其中一個方法專門來做這個事情。

 代碼如下 複製代碼


/**
* 構建ids用於儲存所有表中需要自增的id值,結合findandmodify()來返回對應表最新的id
* @param string $tablename 表名
* @return int
*/
public function get_next_id($tablename = 'topic'){

// db.ids.findAndModify({update:{$inc: {id:1}},query:{tablename:'topic'},new:true});
$data = array(
'findAndModify' => 'ids',
'update' => array( '$inc' => array( 'id' => 1)),
'query' => array('tablename' => $tablename),
'new' => true
);
$idrecord = $this->db()->command( $data );
$newid = $idrecord['value'];

return $newid['id'];
}

// 等同於db.ids.findAndModify({query: {tablename: 'topic'}, update: {$inc: {id: 1}}});

這樣在擷取到最新的id值後,insert event_locations 時需要將id加入到sql語句中(原先id是autoincrement,id欄位沒有在sql中)。之後也就是同樣的商務程序了。

擴充:

有時候可能會遇到一些奇怪的需求,比如一張表裡面有兩個自增id要實現。。。如此,上面的表結構就不能實現了。

 代碼如下 複製代碼

1 <pre>// _id 預設主鍵,mongodb自增 

2 // fieldname  表中自增欄位名 

3 // fieldval 表中自增id值 

4 // tablename 表名</pre>

如此就行了哦

有時候也會碰到一些奇怪的需求,比如要從指定的值如200開始id自增。

那麼其實用這樣一句就可以了

 代碼如下 複製代碼
db.ids.findAndModify({query: {tablename: 'topic'}, update: {id: 200,tablename: 'topic'}});

代碼實現上就是注意要update時要把tablename也要傳遞進去了,因為update會更新所以的記錄,如果不寫上tablename那麼返回的文檔就只有一個id欄位了。。。有需要的自己擴充下吧需要注意的是event_locations id現在不是主鍵也沒有任何索引,除非你加上了;所以這裡還是強烈推薦加上索引

 代碼如下 複製代碼

db.event_locations.ensureIndex({id: 1});

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.