欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

MongoDB中自動(dòng)增長(zhǎng)ID詳解(實(shí)現(xiàn)、應(yīng)用及優(yōu)化)

 更新時(shí)間:2024年06月30日 15:04:40   作者:技術(shù)蜜糖罐  
在MongoDB中,自動(dòng)增長(zhǎng)的功能主要通過(guò)使用數(shù)據(jù)庫(kù)的ObjectId或自定義的序列來(lái)實(shí)現(xiàn),ObjectId是MongoDB默認(rèn)的主鍵類型,它是唯一的并且具有一定的排序特性,本文給大家介紹了MongoDB中自動(dòng)增長(zhǎng)ID,需要的朋友可以參考下

引言

在MongoDB中,自動(dòng)增長(zhǎng)的功能主要通過(guò)使用數(shù)據(jù)庫(kù)的ObjectId或自定義的序列來(lái)實(shí)現(xiàn)。ObjectId是MongoDB默認(rèn)的主鍵類型,它是唯一的并且具有一定的排序特性。然而,在某些場(chǎng)景下,可能需要使用自定義的自動(dòng)增長(zhǎng)ID,例如在某些遺留系統(tǒng)中或者為了更好的用戶體驗(yàn)。

基本語(yǔ)法和命令

使用ObjectId

ObjectId是MongoDB默認(rèn)的主鍵類型,它由12字節(jié)組成,包括時(shí)間戳、機(jī)器標(biāo)識(shí)符、進(jìn)程ID和計(jì)數(shù)器。每次插入新文檔時(shí),MongoDB會(huì)自動(dòng)生成一個(gè)新的ObjectId。

插入新文檔時(shí),_id字段會(huì)自動(dòng)生成:

db.collection.insertOne({name: "example"})

自定義自動(dòng)增長(zhǎng)ID

如果需要自定義自動(dòng)增長(zhǎng)ID,可以使用以下方法:

創(chuàng)建計(jì)數(shù)器集合
創(chuàng)建一個(gè)專門的集合來(lái)存儲(chǔ)序列計(jì)數(shù)器。

db.createCollection("counters")
db.counters.insertOne({_id: "productid", seq: 0})

定義獲取下一個(gè)序列值的函數(shù)
使用findAndModify原子操作來(lái)獲取并增加序列值。

function getNextSequence(name) {
    var ret = db.counters.findAndModify({
        query: { _id: name },
        update: { $inc: { seq: 1 } },
        new: true
    });
    return ret.seq;
}

插入新文檔并使用自定義ID
在插入新文檔時(shí),調(diào)用該函數(shù)以生成新的ID。

db.products.insertOne({
    _id: getNextSequence("productid"),
    name: "example"
})

示例

以下是完整的示例代碼:

  • 創(chuàng)建計(jì)數(shù)器集合并插入初始值:
db.counters.insertOne({_id: "userid", seq: 0})
  • 定義獲取下一個(gè)序列值的函數(shù):
function getNextSequence(name) {
    var ret = db.counters.findAndModify({
        query: { _id: name },
        update: { $inc: { seq: 1 } },
        new: true
    });
    return ret.seq;
}
  • 插入新文檔并使用自定義ID:
db.users.insertOne({
    _id: getNextSequence("userid"),
    name: "John Doe"
})

應(yīng)用場(chǎng)景

1. 遺留系統(tǒng)遷移

詳解:
在許多企業(yè)中,遺留系統(tǒng)使用關(guān)系數(shù)據(jù)庫(kù)(如MySQL、PostgreSQL等),并依賴于自增ID作為主鍵。如果計(jì)劃將這些系統(tǒng)遷移到MongoDB中,直接使用MongoDB的ObjectId可能會(huì)導(dǎo)致兼容性問(wèn)題或破壞現(xiàn)有業(yè)務(wù)邏輯。因此,自定義自動(dòng)增長(zhǎng)ID可以簡(jiǎn)化遷移過(guò)程,保留原有系統(tǒng)的ID生成機(jī)制。

示例場(chǎng)景:
假設(shè)一家電子商務(wù)公司決定將其產(chǎn)品數(shù)據(jù)庫(kù)從MySQL遷移到MongoDB。原系統(tǒng)中的產(chǎn)品ID是自增的整數(shù)。

// MySQL中的產(chǎn)品表
CREATE TABLE products (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(255),
    price DECIMAL(10, 2)
);

// 原有數(shù)據(jù)
INSERT INTO products (name, price) VALUES ('Laptop', 999.99), ('Smartphone', 699.99);

在遷移到MongoDB時(shí),需要保留這些自增的ID。

// 在MongoDB中創(chuàng)建計(jì)數(shù)器集合
db.counters.insertOne({_id: "productid", seq: 2}) // 假設(shè)MySQL中已有兩個(gè)產(chǎn)品

// 定義獲取下一個(gè)序列值的函數(shù)
function getNextSequence(name) {
    var ret = db.counters.findAndModify({
        query: { _id: name },
        update: { $inc: { seq: 1 } },
        new: true
    });
    return ret.seq;
}

// 插入新產(chǎn)品時(shí)使用自定義ID
db.products.insertOne({
    _id: getNextSequence("productid"),
    name: "Tablet",
    price: 499.99
});

2. 用戶友好ID

詳解:
對(duì)于前端用戶,使用連續(xù)的、自增的數(shù)字ID比使用ObjectId更友好、更容易記憶。特別是在需要用戶手動(dòng)輸入或引用ID的場(chǎng)景中,自增ID會(huì)更簡(jiǎn)潔、易讀。

示例場(chǎng)景:
一個(gè)博客平臺(tái)希望用戶能夠通過(guò)短鏈接直接訪問(wèn)文章。使用自增ID可以生成短鏈接,提升用戶體驗(yàn)。

// 創(chuàng)建計(jì)數(shù)器集合
db.counters.insertOne({_id: "postid", seq: 0})

// 定義獲取下一個(gè)序列值的函數(shù)
function getNextSequence(name) {
    var ret = db.counters.findAndModify({
        query: { _id: name },
        update: { $inc: { seq: 1 } },
        new: true
    });
    return ret.seq;
}

// 插入新文章時(shí)使用自定義ID
db.posts.insertOne({
    _id: getNextSequence("postid"),
    title: "How to Use MongoDB",
    content: "MongoDB is a NoSQL database..."
});

// 生成的短鏈接
var postId = getNextSequence("postid");
var shortLink = `http://blogplatform.com/post/${postId}`; // http://blogplatform.com/post/1

3. 特定業(yè)務(wù)需求

詳解
某些業(yè)務(wù)邏輯需要使用連續(xù)的、自增的數(shù)字ID。例如,訂單管理系統(tǒng)可能需要連續(xù)的訂單號(hào),以便于財(cái)務(wù)對(duì)賬和客戶查詢。

示例場(chǎng)景
一家在線零售商需要為每個(gè)訂單生成連續(xù)的訂單號(hào),以便于物流跟蹤和客戶服務(wù)。

// 創(chuàng)建計(jì)數(shù)器集合
db.counters.insertOne({_id: "orderid", seq: 1000}) // 假設(shè)訂單號(hào)從1001開(kāi)始

// 定義獲取下一個(gè)序列值的函數(shù)
function getNextSequence(name) {
    var ret = db.counters.findAndModify({
        query: { _id: name },
        update: { $inc: { seq: 1 } },
        new: true
    });
    return ret.seq;
}

// 插入新訂單時(shí)使用自定義ID
db.orders.insertOne({
    _id: getNextSequence("orderid"),
    customerName: "Alice",
    items: [
        {productId: 1, quantity: 2},
        {productId: 2, quantity: 1}
    ],
    total: 1699.97
});

// 新生成的訂單號(hào)
var orderId = getNextSequence("orderid");
console.log("New Order ID: " + orderId); // New Order ID: 1001

注意事項(xiàng)

1. 并發(fā)問(wèn)題

詳解:
在高并發(fā)環(huán)境中,多個(gè)請(qǐng)求同時(shí)訪問(wèn)計(jì)數(shù)器集合時(shí),必須確保findAndModify操作是原子的,以避免生成重復(fù)ID。MongoDB的findAndModify操作是原子的,它可以保證在高并發(fā)環(huán)境下每次操作都是唯一的,從而避免重復(fù)ID的生成。

示例代碼:

假設(shè)有一個(gè)計(jì)數(shù)器集合counters,我們使用以下代碼來(lái)確保原子性:

// 獲取下一個(gè)自增ID的函數(shù)
function getNextSequenceValue(sequenceName) {
    var sequenceDocument = db.counters.findAndModify({
        query: { _id: sequenceName },
        update: { $inc: { sequence_value: 1 } },
        new: true,
        upsert: true
    });
    return sequenceDocument.sequence_value;
}

// 使用示例
var nextUserId = getNextSequenceValue('user_id');
db.users.insert({ _id: nextUserId, name: "John Doe" });

2. 性能影響

詳解:
頻繁更新計(jì)數(shù)器集合可能會(huì)成為性能瓶頸,尤其是在高并發(fā)環(huán)境中。每次獲取新的ID都需要對(duì)計(jì)數(shù)器集合進(jìn)行讀寫(xiě)操作。這種頻繁的讀寫(xiě)操作可能會(huì)影響數(shù)據(jù)庫(kù)的整體性能。為了解決這個(gè)問(wèn)題,可以考慮使用分布式ID生成算法,如Twitter的Snowflake,它生成的ID不僅是唯一的,而且是分布式的,不需要頻繁訪問(wèn)數(shù)據(jù)庫(kù)。

示例代碼

使用JavaScript實(shí)現(xiàn)簡(jiǎn)單版的Snowflake算法:

class Snowflake {
    constructor(workerId, datacenterId, sequence = 0) {
        this.workerId = workerId;
        this.datacenterId = datacenterId;
        this.sequence = sequence;
        this.twepoch = 1288834974657n;
        this.workerIdBits = 5n;
        this.datacenterIdBits = 5n;
        this.maxWorkerId = -1n ^ (-1n << this.workerIdBits);
        this.maxDatacenterId = -1n ^ (-1n << this.datacenterIdBits);
        this.sequenceBits = 12n;
        this.workerIdShift = this.sequenceBits;
        this.datacenterIdShift = this.sequenceBits + this.workerIdBits;
        this.timestampLeftShift = this.sequenceBits + this.workerIdBits + this.datacenterIdBits;
        this.sequenceMask = -1n ^ (-1n << this.sequenceBits);
        this.lastTimestamp = -1n;
    }

    tilNextMillis(lastTimestamp) {
        let timestamp = this.timeGen();
        while (timestamp <= lastTimestamp) {
            timestamp = this.timeGen();
        }
        return timestamp;
    }

    timeGen() {
        return BigInt(Date.now());
    }

    nextId() {
        let timestamp = this.timeGen();

        if (timestamp < this.lastTimestamp) {
            throw new Error('Clock moved backwards. Refusing to generate id');
        }

        if (this.lastTimestamp === timestamp) {
            this.sequence = (this.sequence + 1n) & this.sequenceMask;
            if (this.sequence === 0n) {
                timestamp = this.tilNextMillis(this.lastTimestamp);
            }
        } else {
            this.sequence = 0n;
        }

        this.lastTimestamp = timestamp;
        return ((timestamp - this.twepoch) << this.timestampLeftShift) |
            (this.datacenterId << this.datacenterIdShift) |
            (this.workerId << this.workerIdShift) |
            this.sequence;
    }
}

// 使用示例
const snowflake = new Snowflake(1n, 1n);
const id = snowflake.nextId();
console.log(id.toString());  // 生成唯一ID

3. 唯一性保證

詳解
在分布式環(huán)境中,確保ID的唯一性是一個(gè)挑戰(zhàn)。即使在多個(gè)節(jié)點(diǎn)上生成ID,也必須保證每個(gè)ID是唯一的。通過(guò)使用分布式ID生成算法(如上所述的Snowflake),可以在多個(gè)節(jié)點(diǎn)上生成唯一的ID,而不需要依賴單一的數(shù)據(jù)庫(kù)計(jì)數(shù)器。

示例代碼

繼續(xù)使用上面的Snowflake示例,在多個(gè)服務(wù)節(jié)點(diǎn)上生成唯一ID:

// 服務(wù)節(jié)點(diǎn)1
const snowflake1 = new Snowflake(1n, 1n);
const id1 = snowflake1.nextId();
console.log(id1.toString());  // 唯一ID

// 服務(wù)節(jié)點(diǎn)2
const snowflake2 = new Snowflake(2n, 1n);
const id2 = snowflake2.nextId();
console.log(id2.toString());  // 唯一ID

通過(guò)以上示例,在不同的服務(wù)節(jié)點(diǎn)上生成的ID仍然是唯一的,確保了分布式環(huán)境中的ID唯一性。

總結(jié)

在MongoDB中,ObjectId提供了一種簡(jiǎn)單且有效的唯一標(biāo)識(shí)符生成方式,但在某些情況下,自定義的自動(dòng)增長(zhǎng)ID可能更適合。通過(guò)創(chuàng)建計(jì)數(shù)器集合和使用findAndModify操作,可以實(shí)現(xiàn)自定義的自動(dòng)增長(zhǎng)ID。需要注意的是,在實(shí)現(xiàn)自定義自動(dòng)增長(zhǎng)ID時(shí),必須處理好并發(fā)和性能問(wèn)題,以確保ID的唯一性和生成效率。

以上就是MongoDB中自動(dòng)增長(zhǎng)ID詳解(實(shí)現(xiàn)、應(yīng)用及優(yōu)化)的詳細(xì)內(nèi)容,更多關(guān)于MongoDB自動(dòng)增長(zhǎng)ID的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • MongoDB 3.4配置文件避免入坑的注意事項(xiàng)

    MongoDB 3.4配置文件避免入坑的注意事項(xiàng)

    最近在配置mongodb的時(shí)候遇到了一些問(wèn)題,現(xiàn)總結(jié)出來(lái)方便以后需要或同樣遇到該問(wèn)題的朋友們參考,下面這篇文章主要給大家介紹了關(guān)于MongoDB 3.4配置文件時(shí)避免入坑的兩個(gè)注意事項(xiàng),需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)下吧。
    2017-09-09
  • Mongodb億級(jí)數(shù)據(jù)性能測(cè)試和壓測(cè)

    Mongodb億級(jí)數(shù)據(jù)性能測(cè)試和壓測(cè)

    MongoDB是一個(gè)開(kāi)源的、基于分布式文件存儲(chǔ)的NoSQL數(shù)據(jù)庫(kù)系統(tǒng),它使用文檔存儲(chǔ)方式,數(shù)據(jù)結(jié)構(gòu)由鍵值(key-value)對(duì)組成,本文給大家介紹了Mongodb億級(jí)數(shù)據(jù)性能測(cè)試和壓測(cè),需要的朋友可以參考下
    2024-06-06
  • Robo可視化mongoDb實(shí)現(xiàn)操作解析

    Robo可視化mongoDb實(shí)現(xiàn)操作解析

    這篇文章主要介紹了Robo可視化mongoDb實(shí)現(xiàn)操作解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-12-12
  • MongoDB復(fù)制集原理詳解

    MongoDB復(fù)制集原理詳解

    這篇文章主要介紹了MongoDB復(fù)制集原理詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-07-07
  • MongoDB數(shù)據(jù)庫(kù)forEach循環(huán)遍歷用法

    MongoDB數(shù)據(jù)庫(kù)forEach循環(huán)遍歷用法

    這篇文章主要介紹了MongoDB數(shù)據(jù)庫(kù)forEach循環(huán)遍歷用法,需要的朋友可以參考下
    2014-07-07
  • MongoDB數(shù)據(jù)庫(kù)部署環(huán)境準(zhǔn)備及使用介紹

    MongoDB數(shù)據(jù)庫(kù)部署環(huán)境準(zhǔn)備及使用介紹

    這篇文章主要為大家介紹了MongoDB數(shù)據(jù)庫(kù)部署環(huán)境準(zhǔn)備以及基本的使用介紹,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-03-03
  • MongoDB中數(shù)據(jù)的替換方法實(shí)現(xiàn)類Replace()函數(shù)功能詳解

    MongoDB中數(shù)據(jù)的替換方法實(shí)現(xiàn)類Replace()函數(shù)功能詳解

    這篇文章主要介紹了MongoDB中數(shù)據(jù)的替換方法實(shí)現(xiàn)類Replace()函數(shù)功能詳解,需要的朋友可以參考下
    2020-02-02
  • 將MongoDB加入到Windows的本地服務(wù)項(xiàng)的方法

    將MongoDB加入到Windows的本地服務(wù)項(xiàng)的方法

    下面主要針對(duì)MongoDB在Windows下加入本地服務(wù)項(xiàng)做一些簡(jiǎn)單的分享。以方便剛接觸MongoDB并在Windows環(huán)境下進(jìn)行開(kāi)發(fā)的同學(xué)
    2014-08-08
  • MongoDB導(dǎo)出查詢結(jié)果到文件例子

    MongoDB導(dǎo)出查詢結(jié)果到文件例子

    這篇文章主要介紹了MongoDB導(dǎo)出查詢結(jié)果到文件例子,本文直接給出示例代碼,簡(jiǎn)潔易懂,需要的朋友可以參考下
    2015-02-02
  • MongoDB的基本安裝與管理命令腳本總結(jié)

    MongoDB的基本安裝與管理命令腳本總結(jié)

    MongoDB是一款高人氣的NoSQL數(shù)據(jù)庫(kù),且以JavaScript代碼作為腳本進(jìn)行操作,對(duì)開(kāi)發(fā)者非常友好,這里我們就來(lái)看一下MongoDB的基本安裝與管理命令腳本總結(jié)
    2016-07-07

最新評(píng)論