在 MongoDB 中自动递增以存储唯一用户 ID 的序列
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8384029/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Auto increment in MongoDB to store sequence of Unique User ID
提问by est
I am making a analytics system, the API call would provide a Unique User ID, but it's not in sequence and too sparse.
我正在制作一个分析系统,API 调用会提供一个唯一的用户 ID,但它没有顺序而且太稀疏。
I need to give each Unique User ID an auto increment id to mark a analytics datapoint in a bitarray/bitset. So the first user encounters would corresponding to the first bit of the bitarray, second user would be the second bit in the bitarray, etc.
我需要给每个唯一用户 ID 一个自动增量 ID 来标记位数组/位集中的分析数据点。因此,第一个用户遇到的将对应于位数组的第一位,第二个用户将是位数组中的第二位,依此类推。
So is there a solid and fast way to generate incremental Unique User IDs in MongoDB?
那么有没有一种可靠且快速的方法来在 MongoDB 中生成增量唯一用户 ID?
采纳答案by Konstantin Pribluda
You can, but you should not https://web.archive.org/web/20151009224806/http://docs.mongodb.org/manual/tutorial/create-an-auto-incrementing-field/
Each object in mongo already has an id, and they are sortable in insertion order. What is wrong with getting collection of user objects, iterating over it and use this as incremented ID? Er go for kind of map-reduce job entirely
mongo 中的每个对象都有一个 id,它们可以按插入顺序排序。获取用户对象的集合、迭代它并将其用作递增的 ID 有什么问题?呃完全去做那种 map-reduce 的工作
回答by expert
As selected answer says you can use findAndModify to generate sequential IDs.
正如所选答案所说,您可以使用 findAndModify 生成顺序 ID。
But I strongly disagree with opinion that you should not do that. It all depends on your business needs. Having 12-byte ID may be very resource consuming and cause significant scalability issues in future.
但我强烈不同意你不应该那样做的观点。这一切都取决于您的业务需求。拥有 12 字节 ID 可能会非常消耗资源,并在未来导致严重的可扩展性问题。
I have detailed answer here.
我在这里有详细的答案。
回答by Alex Nicholas
I know this is an old question, but I shall post my answer for posterity...
我知道这是一个老问题,但我会为后代发布我的答案......
It depends on the system that you are building and the particular business rules in place.
这取决于您正在构建的系统和现有的特定业务规则。
I am building a moderate to large scale CRM in MongoDb, C# (Backend API), and Angular (Frontend web app) and found ObjectId utterly terrible for use in Angular Routing for selecting particular entities. Same with API Controller routing.
我正在用 MongoDb、C#(后端 API)和 Angular(前端 Web 应用程序)构建一个中到大规模的 CRM,并发现 ObjectId 在用于选择特定实体的 Angular Routing 中非常糟糕。与 API 控制器路由相同。
The suggestion above worked perfectly for my project.
上面的建议非常适合我的项目。
db.contacts.insert({
"id":db.contacts.find().Count()+1,
"name":"John Doe",
"emails":[
"[email protected]",
"[email protected]"
],
"phone":"555111322",
"status":"Active"
});
The reason it is perfect for my case, but not all cases is that as the above comment states, if you delete 3 records from the collection, you will get collisions.
它对我的情况来说是完美的,但并非所有情况的原因是,正如上述评论所述,如果您从集合中删除 3 条记录,则会发生冲突。
My business rules state that due to our in house SLA's, we are not allowed to delete correspondence data or clients records for longer than the potential lifespan of the application I'm writing, and therefor, I simply mark records with an enum "Status" which is either "Active" or "Deleted". You can delete something from the UI, and it will say "Contact has been deleted" but all the application has done is change the status of the contact to "Deleted" and when the app calls the respository for a list of contacts, I filter out deleted records before pushing the data to the client app.
我的业务规则规定,由于我们的内部 SLA,我们不允许删除超过我正在编写的应用程序的潜在生命周期的通信数据或客户记录,因此,我只是用枚举“状态”标记记录这是“活动”或“已删除”。您可以从 UI 中删除某些内容,它会说“联系人已被删除”,但应用程序所做的只是将联系人的状态更改为“已删除”,当应用程序调用存储库以获取联系人列表时,我会进行过滤在将数据推送到客户端应用程序之前删除已删除的记录。
Therefore, db.collection.find().count() + 1 is a perfect solution for me...
因此, db.collection.find().count() + 1 对我来说是一个完美的解决方案......
It won't work for everyone, but if you will not be deleting data, it works fine.
它不适用于所有人,但如果您不删除数据,它就可以正常工作。
回答by Darshan Vithani
First Record should be 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;
}
}
回答by MarcoSantana
The best way I found to make this to my purpose was to increment from the max value you have in the field and for that, I used the following syntax:
我发现实现此目的的最佳方法是从您在该字段中拥有的最大值开始递增,为此,我使用了以下语法:
maxObj = db.CollectionName.aggregate([
{
$group : { _id: '$item', maxValue: { $max: '$fieldName' } }
}
];
fieldNextValue = maxObj.maxValue + 1;
$fieldName
is the name of your field, but without the $
sign.
$fieldName
是您的字段的名称,但没有$
符号。
CollectionName
is the name of your collection.
CollectionName
是您的集合的名称。
The reason I am not using count()
is that the produced value could meet an existing value.
我不使用的原因count()
是产生的价值可以满足现有的价值。
The creation of an enforcing unique index could make it safer:
创建强制唯一索引可以使其更安全:
db.CollectionName.createIndex( { "fieldName": 1 }, { unique: true } )
回答by Marian
I had a similar issue, namely I was interested in generating unique numbers, which can be used as identifiers, but doesn't have to. I came up with the following solution. First to initialize the collection:
我有一个类似的问题,即我有兴趣生成唯一的数字,它可以用作标识符,但不是必须的。我想出了以下解决方案。首先初始化集合:
fun create(mongo: MongoTemplate) {
mongo.db.getCollection("sequence")
.insertOne(Document(mapOf("_id" to "globalCounter", "sequenceValue" to 0L)))
}
An then a service that return unique (and ascending) numbers:
然后是返回唯一(和升序)数字的服务:
@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
}
}
I believe that id doesn't have the weaknesses related to concurrent environment that some of the other solutions may suffer from.
我相信 id 没有其他一些解决方案可能遭受的与并发环境相关的弱点。