MongoDB中的自动增量以存储唯一用户ID的序列

时间:2011-12-05 10:38:20

标签: mongodb auto-increment uniqueidentifier bitset bitarray

我正在建立一个分析系统,API调用将提供唯一的用户ID,但它不是按顺序而且太稀疏。

我需要为每个唯一用户ID提供一个自动增量ID,以在bitarray / bitset中标记分析数据点。所以第一个用户遇到的对应于bitarray的第一位,第二个用户将是bitarray中的第二位,等等。

那么在MongoDB中生成增量唯一用户ID有一种可靠而快速的方法吗?

8 个答案:

答案 0 :(得分:18)

如选择的答案所示,您可以使用findAndModify生成顺序ID。

但我强烈不同意你不应该这样做的意见。这一切都取决于您的业务需求。拥有12字节的ID可能非常耗费资源,并且将来会导致严重的可伸缩性问题。

我有详细的答案here

答案 1 :(得分:12)

你可以,但你不应该 https://web.archive.org/web/20151009224806/http://docs.mongodb.org/manual/tutorial/create-an-auto-incrementing-field/

mongo中的每个对象都有一个id,它们按插入顺序排序。获取用户对象的集合,迭代它并将其用作递增的ID有什么问题?呃完全去那种地图减少工作

答案 2 :(得分:7)

我知道这是一个老问题,但我会发布我的答案给后人......

这取决于您正在构建的系统以及适当的特定业务规则。

我正在MongoDb,C#(Backend API)和Angular(前端Web应用程序)中构建中到大型CRM,并发现ObjectId在Angular Routing中用于选择特定实体非常糟糕。与API控制器路由相同。

上述建议对我的项目非常有效。

db.contacts.insert({
 "id":db.contacts.find().Count()+1,
 "name":"John Doe",
 "emails":[
    "john@doe.com",
    "john.doe@business.com"
 ],
 "phone":"555111322",
 "status":"Active"
});

它对我的案例来说是完美的,但不是所有情况都是因为上述评论指出,如果从集合中删除3条记录,则会发生冲突。

我的业务规则规定,由于我们内部的SLA,我们不允许删除通信数据或客户记录超过我正在编写的应用程序的潜在生命周期,因此,我只是用枚举标记记录“状态”,可以是“活动”或“已删除”。你可以从用户界面中删除一些内容,它会说“联系人已被删除”,但所有应用程序已经完成的是将联系人的状态更改为“已删除”,当应用程序调用存储库以获取联系人列表时,我会过滤在将数据推送到客户端应用程序之前删除记录。

因此,db.collection.find()。count()+ 1对我来说是一个完美的解决方案...

它并不适用于所有人,但如果你不删除数据,它就可以正常工作。

答案 3 :(得分:0)

应添加第一条记录

"_id" = 1    in your db

$database = "demo";
$collections ="democollaction";
echo getnextid($database,$collections);

function getnextid($database,$collections){

     $m = new MongoClient();
    $db = $m->selectDB($database);
    $cursor = $collection->find()->sort(array("_id" => -1))->limit(1);
    $array = iterator_to_array($cursor);

    foreach($array as $value){



        return $value["_id"] + 1;

    }
 }

答案 4 :(得分:0)

我发现达到目的的最好方法是从字段中的最大值开始递增,为此,我使用了以下语法:

maxObj = db.CollectionName.aggregate([
  {
    $group : { _id: '$item', maxValue: { $max: '$fieldName' } } 
  }
];
fieldNextValue = maxObj.maxValue + 1;

$fieldName是您的字段的名称,但没有$符号。

CollectionName是您的收藏集的名称。

我不使用count()的原因是产生的值可以满足现有值。

创建强制唯一索引可以使其更安全:

db.CollectionName.createIndex( { "fieldName": 1 }, { unique: true } )

答案 5 :(得分:0)

我有一个类似的问题,即我对生成唯一的数字感兴趣,该数字可以用作标识符,但不必这样做。我想出了以下解决方案。首先初始化集合:

fun create(mongo: MongoTemplate) {
        mongo.db.getCollection("sequence")
                .insertOne(Document(mapOf("_id" to "globalCounter", "sequenceValue" to 0L)))
    }

然后返回唯一(递增)数字的服务:

@Service
class IdCounter(val mongoTemplate: MongoTemplate) {

    companion object {
        const val collection = "sequence"
    }

    private val idField = "_id"
    private val idValue = "globalCounter"
    private val sequence = "sequenceValue"

    fun nextValue(): Long {
        val filter = Document(mapOf(idField to idValue))
        val update = Document("\$inc", Document(mapOf(sequence to 1)))
        val updated: Document = mongoTemplate.db.getCollection(collection).findOneAndUpdate(filter, update)!!
        return updated[sequence] as Long
    }
}

我相信id并没有与其他解决方案可能遭受的并发环境相关的弱点。

答案 6 :(得分:0)

我发现达到目的的最好方法是从字段中的最大值开始递增,为此,我使用了以下语法:

var array = db.CollectionName.find({})。sort({_id:-1})。limit(1).toArray(); var max = max.length?max [0] +1:1;

即使删除了用户ID,也不会创建重复的

答案 7 :(得分:-1)

这可能是另一种方法

const mongoose = require("mongoose");

const contractSchema = mongoose.Schema(
  {
    account: {
      type: mongoose.Schema.Types.ObjectId,
      required: true,
    },
    idContract: {
      type: Number,
      default: 0,
    },
  },
  { timestamps: true }
);

contractSchema.pre("save", function (next) {
  var docs = this;
  mongoose
    .model("contract", contractSchema)
    .countDocuments({ account: docs.account }, function (error, counter) {
      if (error) return next(error);
      docs.idContract = counter + 1;
      next();
    });
});

module.exports = mongoose.model("contract", contractSchema);