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

MongoDB中存储唯一用户ID序列的自动增量,mongodb,auto-increment,uniqueidentifier,bitset,bitarray,Mongodb,Auto Increment,Uniqueidentifier,Bitset,Bitarray,我正在制作一个分析系统,API调用将提供一个唯一的用户ID,但它不是顺序的,而且太稀疏 我需要为每个唯一的用户ID提供一个自动递增ID,以标记位数组/位集中的分析数据点。因此,第一个用户将对应于位数组的第一位,第二个用户将是位数组中的第二位,以此类推 那么,在MongoDB中是否有一种可靠而快速的方法来生成增量唯一用户ID呢?您可以,但不应该 mongo中的每个对象都已经有一个id,并且它们可以按插入顺序排序。获取用户对象集合,对其进行迭代并将其用作递增ID有什么不对?Er选择一种完全减少任务

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

我需要为每个唯一的用户ID提供一个自动递增ID,以标记位数组/位集中的分析数据点。因此,第一个用户将对应于位数组的第一位,第二个用户将是位数组中的第二位,以此类推


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

您可以,但不应该


mongo中的每个对象都已经有一个id,并且它们可以按插入顺序排序。获取用户对象集合,对其进行迭代并将其用作递增ID有什么不对?Er选择一种完全减少任务的map-reduce,因为选择的答案说您可以使用find和modify生成顺序ID

但我强烈不同意你不应该那样做的观点。这完全取决于您的业务需求。拥有12字节的ID可能会非常消耗资源,并在将来导致严重的可伸缩性问题


我有详细的答案。

我知道这是一个老问题,但我会把我的答案留给后代

这取决于您正在构建的系统和特定的业务规则

我正在MongoDb、C#(后端API)和Angular(前端web应用程序)中构建一个中大型CRM,发现ObjectId在Angular路由中用于选择特定实体时非常糟糕。与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,我们不允许删除通信数据或客户记录的时间超过我正在编写的应用程序的潜在使用寿命,因此,我只需使用enum“Status”标记记录,即“Active”或“Deleted”。您可以从UI中删除一些内容,它会显示“联系人已被删除”,但应用程序所做的只是将联系人的状态更改为“已删除”。当应用程序调用respository获取联系人列表时,我会过滤掉已删除的记录,然后将数据推送到客户端应用程序

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


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

第一条记录应该是add

"_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;

    }
 }

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

maxObj = db.CollectionName.aggregate([
  {
    $group : { _id: '$item', maxValue: { $max: '$fieldName' } } 
  }
];
fieldNextValue = maxObj.maxValue + 1;
$fieldName
是字段的名称,但没有
$
符号

CollectionName
是您的收藏的名称

我不使用
count()
的原因是生成的值可能满足现有值

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

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

我有一个类似的问题,即我对生成唯一的数字感兴趣,它可以用作标识符,但不一定非得如此。我提出了以下解决方案。首先初始化集合:

fun create(mongo: MongoTemplate) {
        mongo.db.getCollection("sequence")
                .insertOne(Document(mapOf("_id" to "globalCounter", "sequenceValue" to 0L)))
    }
然后返回唯一(递增)编号的服务:


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

这可能是另一种方法

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);

问题是一致的。iterate将发出重复的增量ID。您只需要此ID进行分析,而不需要数据存储。IIUC,您只需要序列ID作为数组的索引,所以您可以构建位集。您可以在不将增量ID存储在数据库中的情况下实现它,也可以在不向客户端检索数据的情况下构建位数组每次迭代获取增量ID是非常不明智的,尤其是在每个数据点处理数百万用户的情况下。Dong a MAU需要30倍的迭代。当你有数百万用户时,使用增量序列是不明智的。然而,数百万用户也不能很好地使用位阵列,是吗?我发现很难说你到底想达到什么目的。使用
find和modify
不会出现并发问题。另请参阅和HiLo算法:我只想在Mongo中存储一些Redis位图数据,以供以后查询。我遇到了与您相同的问题,即如何生成id以设置位集位置。您解决了这个问题吗?希望这能帮助您。这可能会帮助您:mongodb声明您必须使用函数和计数器序列,而不是使用db.xxx.find.count+1的解析,这有什么特殊原因吗?翻译处理会把事情搞砸吗?您的解决方案在web服务器环境cruds中运行良好吗?谢谢你的回答。这在并行设置中是不好的。如果同时进行计数,您可以轻松获得具有相同id的文档。绝对可以!在我的例子中,我根本不需要处理并发或切分,所以使用find().Count()+1不会有任何问题,正如我最初的回答中所说的,这在任何情况下都不适用于所有人,但在我的特定场景中它确实起到了作用。应用程序已投入生产近12个月,没有关于我的递增id的问题。此解决方案不好,因为您更改了历史记录!一次可能是id为3的文档,另一次可能再次发生。但是具有此id的文档之间没有任何关系,如果您获得的是最大id,而不是count,则会更好。如果您愿意,您可以这样做,我也不同意,因为这是
.createIndex({“number”:1},{unique:true})的mongo内置功能
其中1表示增量和-1otherwise@TinoCosta“ElNino”您所说的不是创建增量字段,而是创建
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);