mongodb 的唯一 ID
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1352671/
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
Unique IDs with mongodb
提问by Alan
If I were building a blog I could use the blog title as the unique identifier and parse it through the URL. However, what if I wanted to use numbers. You know how twitter has www.twitter.com/username/statuses/9834542? Has anyone figured out a nice way of making this work? using "_id" is out of the question since it's way too long.
如果我正在构建一个博客,我可以使用博客标题作为唯一标识符并通过 URL 解析它。但是,如果我想使用数字怎么办。你知道 twitter 如何拥有 www.twitter.com/username/statuses/9834542?有没有人想出一个很好的方法来完成这项工作?使用“_id”是不可能的,因为它太长了。
回答by Alan
As long as you can guarantee uniqueness, you're not constrained to using the default "_id" MongoDB supplies.
只要您能保证唯一性,您就不会被限制使用默认的“_id”MongoDB 供应品。
Therefore, it's down to you how you generate this number. If you'd like to store this number inside MongoDB, then you could store it in a separate collection and increment it for every new URL required.
因此,这取决于您如何生成此数字。如果您想将这个数字存储在 MongoDB 中,那么您可以将它存储在一个单独的集合中,并为每个需要的新 URL 增加它。
Incrementing a field is achieved by using the $inc
verb, or you may want to take a look at how MongoDB can atomically updateor increment a value.
回答by Hubert Kario
It can be done by using the findandmodifycommand.
这可以通过使用findandmodify命令来完成。
Let's consider we have a special collection named sequences
and we want to have a sequence for post numbers (named postid
), you could use code similar to this:
假设我们有一个名为的特殊集合,sequences
并且我们想要一个帖子编号(名为postid
)的序列,您可以使用类似于以下的代码:
> db.runCommand( { "findandmodify" : "sequences", "query" : { "name" : "postid"}, "update" : { $inc : { "id" : 1 }}, "new" : true } );
This command will return atomically the updated (new
) document together with status. The value
field contains the returned document if the command completed successfully.
此命令将自动返回更新的 ( new
) 文档和状态。value
如果命令成功完成,该字段包含返回的文档。
回答by Van Nguyen
If you want to add a uniqueness constraint to your own field in MongoDB, use an index. Then you can use any hashing algorithm you want to generate the number and test it for uniqueness. The example in the MongoDB documentation is
如果要在 MongoDB 中为自己的字段添加唯一性约束,请使用索引。然后你可以使用任何你想要生成数字的哈希算法并测试它的唯一性。MongoDB 文档中的示例是
db.things.ensureIndex({firstname: 1, lastname: 1}, {unique: true});
which will prevent you from inserting documents with the same firstname AND lastname as another document.
这将阻止您插入与另一个文档具有相同名字和姓氏的文档。
More information is available in the documentation.
文档中提供了更多信息。
回答by vmorarian
I have solved this problem by creating collection 'sequence' with data:
我通过使用数据创建集合“序列”解决了这个问题:
- name
- currurt value
- 姓名
- 当前价值
I'm using Morhpia, so have DAO for it. But you can do it without Morhpia too. Idea is to use $atomic (probably it can be omitted due updateing 1 instance only) and $incmodifier operator.
我正在使用Morhpia,所以使用 DAO 。但是你也可以在没有 Morhpia 的情况下做到这一点。想法是使用 $atomic (可能由于仅更新 1 个实例而可以省略它)和$inc修饰符运算符。
Sequence
序列
@Entity(value = "sys_sequence", noClassnameStored = true)
public class SequenceM {
/**
* Names of entity
*/
public static enum Entity {
USER,
CAPABILITY_HISTORY;
public String getEntityName() {
return this.name().toLowerCase();
}
}
@Id
private ObjectId uid;
@Property
@Indexed(unique = true)
private String name;
@Property
private Long value;
//..getters/setters/etc
}
Method on SequenceDAO:
SequenceDAO 上的方法:
@NotNull
public Long nextValue(final @NotNull SequenceM.Entity entity) {
final DB db = this.ds.getDB();
final WriteConcern writeConcern = getWriteConcern();
//optimization for JVM instance
synchronized(entity) {
do {
SequenceM sequence = findOne("name", entity.getEntityName());
final DBObject q = BasicDBObjectBuilder.start().add("name", entity.getEntityName()).add("value", sequence.getValue()).add("$atomic", 1).get();
final DBObject o = BasicDBObjectBuilder.start().add("$inc", BasicDBObjectBuilder.start().add("value", 1).get()).get();
WriteResult writeResult = db.getCollection("sys_sequence").update(q, o, false, true, writeConcern);
if(writeResult.getN() == 1) {
return sequence.getValue() + 1;
}
} while(true);
}
}
/**
* Determining writing concern basing on configuration
*/
private WriteConcern getWriteConcern() {
return isOneNodeOnly ? WriteConcern.SAFE : REPLICATION_SAFE;
}
Depending on MongoDB configuration (one node only or master/slave or replica set) you have to use correct WriteConcern. Using REPLICATION_SAFE in one environment with one instance only causes infinite loop.
根据 MongoDB 配置(仅一个节点或主/从或副本集),您必须使用正确的 WriteConcern。在一个只有一个实例的环境中使用 REPLICATION_SAFE 只会导致无限循环。
回答by vmorarian
Technically, the ID number is too large to shorten it. However, a tactic can be filled. That is passing from Hex to alphanumeric, thus reducing the number of characters to tulizar and looks more beautiful in the Url. I really served very well ... here is
从技术上讲,ID 号太大而无法将其缩短。但是,可以填充一个策略。那是从十六进制转换为字母数字,从而减少了 tulizar 的字符数,并且在 Url 中看起来更漂亮。我真的服务很好......这里是
function encode(hex) {
return new Buffer(hex, 'hex').toString('base64').replace('+', '-').replace('/', '_');
};
function decode(NoHex) {
return new Buffer( NoHex.replace('-','+').replace('_','/'), 'base64').toString('hex');
};
IdString= MyDoc._id.toString();
Idencode = encode( IdString ) // 16 Caracters a-Z and 0-9
console.log( IdEncode ); //You see That 'aqswedasdfdsadsf'
IdDecode = decode( IdEncode );
IdDecode === IdString // Is true!!!
Of course this technique uses the same id, mongo.
当然,这种技术使用相同的 id,mongo。